[med-svn] [Git][med-team/libvcflib][upstream] New upstream version 1.0.3+dfsg

Nilesh Patra (@nilesh) gitlab at salsa.debian.org
Sun Feb 20 18:17:31 GMT 2022



Nilesh Patra pushed to branch upstream at Debian Med / libvcflib


Commits:
5623aedd by Nilesh Patra at 2022-02-20T18:05:16+00:00
New upstream version 1.0.3+dfsg
- - - - -


29 changed files:

- − .travis.yml
- + filevercmp/.gitignore
- + filevercmp/Makefile
- + filevercmp/README.md
- + filevercmp/filevercmp.c
- + filevercmp/filevercmp.h
- + filevercmp/main.c
- + intervaltree/.gitignore
- + intervaltree/IntervalTree.h
- + intervaltree/LICENSE
- + intervaltree/Makefile
- + intervaltree/README.md
- + intervaltree/catch.hpp
- + intervaltree/interval_tree_test.cpp
- + multichoose/.gitignore
- + multichoose/LICENSE
- + multichoose/Makefile
- + multichoose/README.md
- + multichoose/cli.js
- + multichoose/index.js
- + multichoose/multichoose.c
- + multichoose/multichoose.cpp
- + multichoose/multichoose.h
- + multichoose/multichoose.py
- + multichoose/multipermute.cpp
- + multichoose/multipermute.h
- + multichoose/multipermute.py
- + multichoose/package.json
- + multichoose/test.js


Changes:

=====================================
.travis.yml deleted
=====================================
@@ -1,20 +0,0 @@
-matrix:
-  include:
-    - os: linux
-      dist: focal
-      arch:
-        - arm64
-      compiler: gcc
-      addons:
-        apt:
-          packages:
-            - libhts-dev
-            - libtabixpp-dev 
-            - libtabixpp0
-script:
-    - pkg-config --list-all
-    - mkdir -p build
-    - cd build
-    - cmake ..
-    - cmake --build . --verbose
-    - ctest --verbose


=====================================
filevercmp/.gitignore
=====================================
@@ -0,0 +1,3 @@
+filevercmp.o
+filevercmp
+*~


=====================================
filevercmp/Makefile
=====================================
@@ -0,0 +1,13 @@
+all: filevercmp
+
+clean:
+	rm -f filevercmp
+	rm -f filevercmp.o
+
+.PHONY: all clean
+
+filevercmp.o: filevercmp.c main.c filevercmp.h
+	gcc -c filevercmp.c
+
+filevercmp: filevercmp.o
+	gcc -o filevercmp main.c filevercmp.o


=====================================
filevercmp/README.md
=====================================
@@ -0,0 +1,39 @@
+Compare version strings:
+
+This function compares strings S1 and S2:
+
+1. By PREFIX in the same way as strcmp.
+2. Then by VERSION (most similarly to version compare of Debian's dpkg).
+  Leading zeros in version numbers are ignored.
+3. If both (PREFIX and  VERSION) are equal, strcmp function is used for
+  comparison. So this function can return 0 if (and only if) strings S1
+  and S2 are identical.
+
+It returns number >0 for S1 > S2, 0 for S1 == S2 and number <0 for S1 < S2.
+
+This function compares strings, in a way that if VER1 and VER2 are version
+numbers and PREFIX and SUFFIX (SUFFIX defined as `(\.[A-Za-z~][A-Za-z0-9~]*)*)`
+are strings then VER1 < VER2 implies filevercmp (PREFIX VER1 SUFFIX,
+PREFIX VER2 SUFFIX) < 0.
+
+This function is intended to be a replacement for strverscmp.
+
+*fine print*
+
+
+    Copyright (C) 1995 Ian Jackson <iwj10 at cus.cam.ac.uk>
+    Copyright (C) 2001 Anthony Towns <aj at azure.humbug.org.au>
+    Copyright (C) 2008-2009 Free Software Foundation, Inc.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>..


=====================================
filevercmp/filevercmp.c
=====================================
@@ -0,0 +1,180 @@
+/*
+   Copyright (C) 1995 Ian Jackson <iwj10 at cus.cam.ac.uk>
+   Copyright (C) 2001 Anthony Towns <aj at azure.humbug.org.au>
+   Copyright (C) 2008-2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include "filevercmp.h"
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+/* Match a file suffix defined by this regular expression:
+   /(\.[A-Za-z~][A-Za-z0-9~]*)*$/
+   Scan the string *STR and return a pointer to the matching suffix, or
+   NULL if not found.  Upon return, *STR points to terminating NUL.  */
+static const char *
+match_suffix (const char **str)
+{
+  const char *match = NULL;
+  bool read_alpha = false;
+  while (**str)
+    {
+      if (read_alpha)
+        {
+          read_alpha = false;
+          if (!isalpha (**str) && '~' != **str)
+            match = NULL;
+        }
+      else if ('.' == **str)
+        {
+          read_alpha = true;
+          if (!match)
+            match = *str;
+        }
+      else if (!isalnum (**str) && '~' != **str)
+        match = NULL;
+      (*str)++;
+    }
+  return match;
+}
+
+/* verrevcmp helper function */
+static inline int
+order (unsigned char c)
+{
+  if (isdigit (c))
+    return 0;
+  else if (isalpha (c))
+    return c;
+  else if (c == '~')
+    return -1;
+  else
+    return (int) c + UCHAR_MAX + 1;
+}
+
+/* slightly modified verrevcmp function from dpkg
+   S1, S2 - compared string
+   S1_LEN, S2_LEN - length of strings to be scanned
+
+   This implements the algorithm for comparison of version strings
+   specified by Debian and now widely adopted.  The detailed
+   specification can be found in the Debian Policy Manual in the
+   section on the `Version' control field.  This version of the code
+   implements that from s5.6.12 of Debian Policy v3.8.0.1
+   http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version */
+static int
+verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
+{
+  size_t s1_pos = 0;
+  size_t s2_pos = 0;
+  while (s1_pos < s1_len || s2_pos < s2_len)
+    {
+      int first_diff = 0;
+      while ((s1_pos < s1_len && !isdigit (s1[s1_pos]))
+	     || (s2_pos < s2_len && !isdigit (s2[s2_pos])))
+	{
+	  int s1_c = (s1_pos == s1_len) ? 0 : order (s1[s1_pos]);
+	  int s2_c = (s2_pos == s2_len) ? 0 : order (s2[s2_pos]);
+	  if (s1_c != s2_c)
+	    return s1_c - s2_c;
+	  s1_pos++;
+	  s2_pos++;
+	}
+      while (s1[s1_pos] == '0')
+	s1_pos++;
+      while (s2[s2_pos] == '0')
+	s2_pos++;
+      while (isdigit (s1[s1_pos]) && isdigit (s2[s2_pos]))
+	{
+	  if (!first_diff)
+	    first_diff = s1[s1_pos] - s2[s2_pos];
+	  s1_pos++;
+	  s2_pos++;
+	}
+      if (isdigit (s1[s1_pos]))
+	return 1;
+      if (isdigit (s2[s2_pos]))
+	return -1;
+      if (first_diff)
+	return first_diff;
+    }
+  return 0;
+}
+
+/* Compare version strings S1 and S2.
+   See filevercmp.h for function description.  */
+int
+filevercmp (const char *s1, const char *s2)
+{
+  const char *s1_pos;
+  const char *s2_pos;
+  const char *s1_suffix, *s2_suffix;
+  size_t s1_len, s2_len;
+  int result;
+
+  /* easy comparison to see if strings are identical */
+  int simple_cmp = strcmp (s1, s2);
+  if (simple_cmp == 0)
+    return 0;
+
+  /* special handle for "", "." and ".." */
+  if (!*s1)
+    return -1;
+  if (!*s2)
+    return 1;
+  if (0 == strcmp (".", s1))
+    return -1;
+  if (0 == strcmp (".", s2))
+    return 1;
+  if (0 == strcmp ("..", s1))
+    return -1;
+  if (0 == strcmp ("..", s2))
+    return 1;
+
+  /* special handle for other hidden files */
+  if (*s1 == '.' && *s2 != '.')
+    return -1;
+  if (*s1 != '.' && *s2 == '.')
+    return 1;
+  if (*s1 == '.' && *s2 == '.')
+    {
+      s1++;
+      s2++;
+    }
+
+  /* "cut" file suffixes */
+  s1_pos = s1;
+  s2_pos = s2;
+  s1_suffix = match_suffix (&s1_pos);
+  s2_suffix = match_suffix (&s2_pos);
+  s1_len = (s1_suffix ? s1_suffix : s1_pos) - s1;
+  s2_len = (s2_suffix ? s2_suffix : s2_pos) - s2;
+
+  /* restore file suffixes if strings are identical after "cut" */
+  if ((s1_suffix || s2_suffix) && (s1_len == s2_len)
+      && 0 == strncmp (s1, s2, s1_len))
+    {
+      s1_len = s1_pos - s1;
+      s2_len = s2_pos - s2;
+    }
+
+  result = verrevcmp (s1, s1_len, s2, s2_len);
+  return result == 0 ? simple_cmp : result;
+}


=====================================
filevercmp/filevercmp.h
=====================================
@@ -0,0 +1,42 @@
+/*
+   Copyright (C) 1995 Ian Jackson <iwj10 at cus.cam.ac.uk>
+   Copyright (C) 2001 Anthony Towns <aj at azure.humbug.org.au>
+   Copyright (C) 2008-2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FILEVERCMP_H
+#define FILEVERCMP_H
+
+/* Compare version strings:
+
+   This function compares strings S1 and S2:
+   1) By PREFIX in the same way as strcmp.
+   2) Then by VERSION (most similarly to version compare of Debian's dpkg).
+      Leading zeros in version numbers are ignored.
+   3) If both (PREFIX and  VERSION) are equal, strcmp function is used for
+      comparison. So this function can return 0 if (and only if) strings S1
+      and S2 are identical.
+
+   It returns number >0 for S1 > S2, 0 for S1 == S2 and number <0 for S1 < S2.
+
+   This function compares strings, in a way that if VER1 and VER2 are version
+   numbers and PREFIX and SUFFIX (SUFFIX defined as (\.[A-Za-z~][A-Za-z0-9~]*)*)
+   are strings then VER1 < VER2 implies filevercmp (PREFIX VER1 SUFFIX,
+   PREFIX VER2 SUFFIX) < 0.
+
+   This function is intended to be a replacement for strverscmp. */
+int filevercmp (const char *s1, const char *s2);
+
+#endif /* FILEVERCMP_H */


=====================================
filevercmp/main.c
=====================================
@@ -0,0 +1,15 @@
+#include "filevercmp.h"
+#include <stdio.h>
+
+
+int main(int argc, char** argv) {
+    if (argc != 3) {
+        printf("usage: %s [a] [b]\n", argv[0]);
+        printf("shows version-string comparison of strings a and b\n");
+        printf("for instance, chr1 < chr10, 1 < 10, abca < bcac\n");
+        return 1;
+    }
+    int c = filevercmp(argv[1], argv[2]);
+    printf("%s < %s = %i\n", argv[1], argv[2], c);
+    return 0;
+}


=====================================
intervaltree/.gitignore
=====================================
@@ -0,0 +1 @@
+interval_tree_test


=====================================
intervaltree/IntervalTree.h
=====================================
@@ -0,0 +1,344 @@
+#ifndef __INTERVAL_TREE_H
+#define __INTERVAL_TREE_H
+
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <memory>
+#include <cassert>
+#include <limits>
+
+#ifdef USE_INTERVAL_TREE_NAMESPACE
+namespace interval_tree {
+#endif
+template <class Scalar, typename Value>
+class Interval {
+public:
+    Scalar start;
+    Scalar stop;
+    Value value;
+    Interval(const Scalar& s, const Scalar& e, const Value& v)
+    : start(std::min(s, e))
+    , stop(std::max(s, e))
+    , value(v) 
+    {}
+};
+
+template <class Scalar, typename Value>
+Value intervalStart(const Interval<Scalar,Value>& i) {
+    return i.start;
+}
+
+template <class Scalar, typename Value>
+Value intervalStop(const Interval<Scalar, Value>& i) {
+    return i.stop;
+}
+
+template <class Scalar, typename Value>
+std::ostream& operator<<(std::ostream& out, const Interval<Scalar, Value>& i) {
+    out << "Interval(" << i.start << ", " << i.stop << "): " << i.value;
+    return out;
+}
+
+template <class Scalar, class Value>
+class IntervalTree {
+public:
+    typedef Interval<Scalar, Value> interval;
+    typedef std::vector<interval> interval_vector;
+
+
+    struct IntervalStartCmp {
+        bool operator()(const interval& a, const interval& b) {
+            return a.start < b.start;
+        }
+    };
+
+    struct IntervalStopCmp {
+        bool operator()(const interval& a, const interval& b) {
+            return a.stop < b.stop;
+        }
+    };
+
+    IntervalTree()
+        : left(nullptr)
+        , right(nullptr)
+        , center(0)
+    {}
+
+    ~IntervalTree() = default;
+
+    std::unique_ptr<IntervalTree> clone() const {
+        return std::unique_ptr<IntervalTree>(new IntervalTree(*this));
+    }
+
+    IntervalTree(const IntervalTree& other)
+    :   intervals(other.intervals),
+        left(other.left ? other.left->clone() : nullptr),
+        right(other.right ? other.right->clone() : nullptr),
+        center(other.center)
+    {}
+
+    IntervalTree& operator=(IntervalTree&&) = default;
+    IntervalTree(IntervalTree&&) = default;
+
+    IntervalTree& operator=(const IntervalTree& other) {
+        center = other.center;
+        intervals = other.intervals;
+        left = other.left ? other.left->clone() : nullptr;
+        right = other.right ? other.right->clone() : nullptr;
+        return *this;
+    }
+
+    IntervalTree(
+            interval_vector&& ivals,
+            std::size_t depth = 16,
+            std::size_t minbucket = 64,
+            std::size_t maxbucket = 512, 
+            Scalar leftextent = 0,
+            Scalar rightextent = 0)
+      : left(nullptr)
+      , right(nullptr)
+    {
+        --depth;
+        const auto minmaxStop = std::minmax_element(ivals.begin(), ivals.end(), 
+                                                    IntervalStopCmp());
+        const auto minmaxStart = std::minmax_element(ivals.begin(), ivals.end(), 
+                                                     IntervalStartCmp());
+        if (!ivals.empty()) {
+            center = (minmaxStart.first->start + minmaxStop.second->stop) / 2;
+        }
+        if (leftextent == 0 && rightextent == 0) {
+            // sort intervals by start
+            std::sort(ivals.begin(), ivals.end(), IntervalStartCmp());
+        } else {
+            assert(std::is_sorted(ivals.begin(), ivals.end(), IntervalStartCmp()));
+        }
+        if (depth == 0 || (ivals.size() < minbucket && ivals.size() < maxbucket)) {
+            std::sort(ivals.begin(), ivals.end(), IntervalStartCmp());
+            intervals = std::move(ivals);
+            assert(is_valid().first);
+            return;
+        } else {
+            Scalar leftp = 0;
+            Scalar rightp = 0;
+
+            if (leftextent || rightextent) {
+                leftp = leftextent;
+                rightp = rightextent;
+            } else {
+                leftp = ivals.front().start;
+                rightp = std::max_element(ivals.begin(), ivals.end(),
+                                          IntervalStopCmp())->stop;
+            }
+
+            interval_vector lefts;
+            interval_vector rights;
+
+            for (typename interval_vector::const_iterator i = ivals.begin(); 
+                 i != ivals.end(); ++i) {
+                const interval& interval = *i;
+                if (interval.stop < center) {
+                    lefts.push_back(interval);
+                } else if (interval.start > center) {
+                    rights.push_back(interval);
+                } else {
+                    assert(interval.start <= center);
+                    assert(center <= interval.stop);
+                    intervals.push_back(interval);
+                }
+            }
+
+            if (!lefts.empty()) {
+                left.reset(new IntervalTree(std::move(lefts), 
+                                            depth, minbucket, maxbucket,
+                                            leftp, center));
+            }
+            if (!rights.empty()) {
+                right.reset(new IntervalTree(std::move(rights), 
+                                             depth, minbucket, maxbucket, 
+                                             center, rightp));
+            }
+        }
+        assert(is_valid().first);
+    }
+
+    // Call f on all intervals near the range [start, stop]:
+    template <class UnaryFunction>
+    void visit_near(const Scalar& start, const Scalar& stop, UnaryFunction f) const {
+        if (!intervals.empty() && ! (stop < intervals.front().start)) {
+            for (auto & i : intervals) {
+              f(i);
+            }
+        }
+        if (left && start <= center) {
+            left->visit_near(start, stop, f);
+        }
+        if (right && stop >= center) {
+            right->visit_near(start, stop, f);
+        }
+    }
+
+    // Call f on all intervals crossing pos
+    template <class UnaryFunction>
+    void visit_overlapping(const Scalar& pos, UnaryFunction f) const {
+        visit_overlapping(pos, pos, f);
+    }
+
+    // Call f on all intervals overlapping [start, stop]
+    template <class UnaryFunction>
+    void visit_overlapping(const Scalar& start, const Scalar& stop, UnaryFunction f) const {
+        auto filterF = [&](const interval& interval) {
+            if (interval.stop >= start && interval.start <= stop) {
+                // Only apply f if overlapping
+                f(interval);
+            }
+        };
+        visit_near(start, stop, filterF);
+    }
+
+    // Call f on all intervals contained within [start, stop]
+    template <class UnaryFunction>
+    void visit_contained(const Scalar& start, const Scalar& stop, UnaryFunction f) const {
+        auto filterF = [&](const interval& interval) {
+            if (start <= interval.start && interval.stop <= stop) {
+                f(interval);
+            }
+        };
+        visit_near(start, stop, filterF);
+    }
+
+    interval_vector findOverlapping(const Scalar& start, const Scalar& stop) const {
+        interval_vector result;
+        visit_overlapping(start, stop,
+                          [&](const interval& interval) { 
+                            result.emplace_back(interval); 
+                          });
+        return result;
+    }
+
+    interval_vector findContained(const Scalar& start, const Scalar& stop) const {
+        interval_vector result;
+        visit_contained(start, stop,
+                        [&](const interval& interval) { 
+                          result.push_back(interval); 
+                        });
+        return result;
+    }
+    bool empty() const {
+        if (left && !left->empty()) {
+            return false;
+        }
+        if (!intervals.empty()) { 
+            return false;
+        }
+        if (right && !right->empty()) {
+            return false;
+        }
+        return true;
+    }
+
+    template <class UnaryFunction>
+    void visit_all(UnaryFunction f) const {
+        if (left) {
+            left->visit_all(f);
+        }
+        std::for_each(intervals.begin(), intervals.end(), f);
+        if (right) {
+            right->visit_all(f);
+        }
+    }
+
+    std::pair<Scalar, Scalar> extentBruitForce() const {
+        struct Extent {
+            std::pair<Scalar, Scalar> x = {std::numeric_limits<Scalar>::max(),
+                                                       std::numeric_limits<Scalar>::min() };
+            void operator()(const interval & interval) {
+                x.first  = std::min(x.first,  interval.start);
+                x.second = std::max(x.second, interval.stop);
+            }
+                                                                };
+                                            Extent extent;
+
+        visit_all([&](const interval & interval) { extent(interval); });
+        return extent.x;
+                                            }
+
+    // Check all constraints.
+    // If first is false, second is invalid.
+    std::pair<bool, std::pair<Scalar, Scalar>> is_valid() const {
+        const auto minmaxStop = std::minmax_element(intervals.begin(), intervals.end(), 
+                                                    IntervalStopCmp());
+        const auto minmaxStart = std::minmax_element(intervals.begin(), intervals.end(), 
+                                                     IntervalStartCmp());
+        
+        std::pair<bool, std::pair<Scalar, Scalar>> result = {true, { std::numeric_limits<Scalar>::max(),
+                                                                     std::numeric_limits<Scalar>::min() }};
+        if (!intervals.empty()) {
+            result.second.first   = std::min(result.second.first,  minmaxStart.first->start);
+            result.second.second  = std::min(result.second.second, minmaxStop.second->stop);
+        }
+        if (left) {
+            auto valid = left->is_valid();
+            result.first &= valid.first;
+            result.second.first   = std::min(result.second.first,  valid.second.first);
+            result.second.second  = std::min(result.second.second, valid.second.second);
+            if (!result.first) { return result; }
+            if (valid.second.second >= center) {
+                result.first = false;
+                return result;
+            }
+        }
+        if (right) {
+            auto valid = right->is_valid();
+            result.first &= valid.first;
+            result.second.first   = std::min(result.second.first,  valid.second.first);
+            result.second.second  = std::min(result.second.second, valid.second.second);
+            if (!result.first) { return result; }
+            if (valid.second.first <= center) { 
+                result.first = false;
+                return result;
+            }
+        }
+        if (!std::is_sorted(intervals.begin(), intervals.end(), IntervalStartCmp())) {
+            result.first = false;
+        }
+        return result;        
+    }
+
+    friend std::ostream& operator<<(std::ostream& os, const IntervalTree& itree) {
+        return writeOut(os, itree);
+    }
+
+    friend std::ostream& writeOut(std::ostream& os, const IntervalTree& itree, 
+                                  std::size_t depth = 0) {
+        auto pad = [&]() { for (std::size_t i = 0; i != depth; ++i) { os << ' '; } };
+        pad(); os << "center: " << itree.center << '\n';
+        for (const interval & inter : itree.intervals) {
+            pad(); os << inter << '\n';
+        }
+        if (itree.left) {
+            pad(); os << "left:\n";
+            writeOut(os, *itree.left, depth + 1);
+        } else {
+            pad(); os << "left: nullptr\n";
+        }
+        if (itree.right) {
+            pad(); os << "right:\n";
+            writeOut(os, *itree.right, depth + 1);
+        } else {
+            pad(); os << "right: nullptr\n";
+        }
+        return os;
+    }
+
+private:
+    interval_vector intervals;
+    std::unique_ptr<IntervalTree> left;
+    std::unique_ptr<IntervalTree> right;
+    Scalar center;
+};
+#ifdef USE_INTERVAL_TREE_NAMESPACE
+}
+#endif
+
+#endif


=====================================
intervaltree/LICENSE
=====================================
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Erik Garrison
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.


=====================================
intervaltree/Makefile
=====================================
@@ -0,0 +1,37 @@
+
+# Use ?= to allow overriding from the env or command-line, e.g.
+#
+#	make CXXFLAGS="-O3 -fPIC" install
+#
+# Package managers will override many of these variables automatically, so
+# this is aimed at making it easy to create packages (Debian packages,
+# FreeBSD ports, MacPorts, pkgsrc, etc.)
+
+CXX ?=		c++
+CXXFLAGS +=	-Wall
+DESTDIR ?=	stage
+PREFIX ?=	/usr/local
+MKDIR ?=	mkdir
+INSTALL ?=	install -c
+STRIP ?=	strip
+
+BIN =	interval_tree_test
+
+all: ${BIN}
+
+${BIN}: interval_tree_test.cpp IntervalTree.h
+	${CXX} $(CPPFLAGS) ${CXXFLAGS} $(LDFLAGS) interval_tree_test.cpp -std=c++0x -o ${BIN}
+
+install: all
+	${MKDIR} -p ${DESTDIR}${PREFIX}/bin
+	${MKDIR} -p ${DESTDIR}${PREFIX}/include/intervaltree
+	${INSTALL} ${BIN} ${DESTDIR}${PREFIX}/bin
+	${INSTALL} IntervalTree.h ${DESTDIR}${PREFIX}/include/intervaltree
+
+install-strip: install
+	${STRIP} ${DESTDIR}${PREFIX}/bin/${BIN}
+
+.PHONY: clean
+
+clean:
+	rm -rf ${BIN} ${DESTDIR}


=====================================
intervaltree/README.md
=====================================
@@ -0,0 +1,37 @@
+# intervaltree
+
+## Overview
+
+An interval tree can be used to efficiently find a set of numeric intervals overlapping or containing another interval.
+
+This library provides a basic implementation of an interval tree using C++ templates, allowing the insertion of arbitrary types into the tree.
+
+## Usage
+
+Add `#include "IntervalTree.h"` to the source files in which you will use the interval tree.
+
+To make an IntervalTree to contain objects of class T, use:
+
+```c++
+vector<Interval<T> > intervals;
+T a, b, c;
+intervals.push_back(Interval<T>(2, 10, a));
+intervals.push_back(Interval<T>(3, 4, b));
+intervals.push_back(Interval<T>(20, 100, c));
+IntervalTree<T> tree;
+tree = IntervalTree<T>(intervals);
+```
+
+Now, it's possible to query the tree and obtain a set of intervals which are contained within the start and stop coordinates.
+
+```c++
+vector<Interval<T> > results;
+tree.findContained(start, stop, results);
+cout << "found " << results.size() << " overlapping intervals" << endl;
+```
+
+The function IntervalTree::findOverlapping provides a method to find all those intervals which are contained or partially overlap the interval (start, stop).
+
+### Author: Erik Garrison <erik.garrison at gmail.com>
+
+### License: MIT


=====================================
intervaltree/catch.hpp
=====================================
The diff for this file was not included because it is too large.

=====================================
intervaltree/interval_tree_test.cpp
=====================================
@@ -0,0 +1,189 @@
+#include <iostream>
+#include <thread>
+#include <chrono>
+#include <random>
+#include <limits>
+#include <time.h>
+#include <assert.h>
+#include "IntervalTree.h"
+#define CATCH_CONFIG_RUNNER // Mark this as file as the test-runner for catch
+#include "catch.hpp"        // Include the catch unit test framework
+
+using namespace std;
+
+typedef IntervalTree<std::size_t, bool> intervalTree;
+typedef intervalTree::interval interval;
+typedef intervalTree::interval_vector intervalVector;
+
+TEST_CASE( "Empty tree" ) {
+    IntervalTree<std::size_t, int> t;
+    REQUIRE( t.findOverlapping(-1,1).size() == 0 );
+}
+
+TEST_CASE( "Singleton tree" ) {
+  IntervalTree<std::size_t, double> t{ {{1,3,5.5}},
+                                       1, 64, 512};
+
+    SECTION ("Point query on left") {
+	auto v = t.findOverlapping(1,1);
+	REQUIRE( v.size() == 1);
+	REQUIRE( v.front().start == 1 );
+	REQUIRE( v.front().stop == 3 );
+	REQUIRE( v.front().value == 5.5 );
+    }
+
+    SECTION ("Wild search values") {
+        typedef IntervalTree<double, std::size_t> IT;
+        IT t { {{0.0, 1.0, 0}} };
+        const auto inf = std::numeric_limits<double>::infinity();
+        const auto nan = std::numeric_limits<double>::quiet_NaN();
+        auto sanityResults = t.findOverlapping(inf, inf);
+        assert(sanityResults.size() == 0);
+        sanityResults = t.findOverlapping(-inf, inf);
+        assert(sanityResults.size() == 1);
+        sanityResults = t.findOverlapping(0, inf);
+        assert(sanityResults.size() == 1);
+        sanityResults = t.findOverlapping(0.5, inf);
+        assert(sanityResults.size() == 1);
+        sanityResults = t.findOverlapping(1.1, inf);
+        assert(sanityResults.size() == 0);
+        sanityResults = t.findOverlapping(-inf, 1.0);
+        assert(sanityResults.size() == 1);
+        sanityResults = t.findOverlapping(-inf, 0.5);
+        assert(sanityResults.size() == 1);
+        sanityResults = t.findOverlapping(-inf, 0.0);
+        assert(sanityResults.size() == 1);
+        sanityResults = t.findOverlapping(-inf, -0.1);
+        assert(sanityResults.size() == 0);
+        sanityResults = t.findOverlapping(nan, nan);
+        assert(sanityResults.size() == 0);
+        sanityResults = t.findOverlapping(-nan, nan);
+        assert(sanityResults.size() == 0);
+        sanityResults = t.findOverlapping(nan, 1);
+        assert(sanityResults.size() == 0);
+        sanityResults = t.findOverlapping(0, nan);
+        assert(sanityResults.size() == 0);
+    }
+
+    SECTION ("Point query in middle") {
+	auto v = t.findOverlapping(2,2);
+	REQUIRE( v.size() == 1);
+	REQUIRE( v.front().start == 1 );
+	REQUIRE( v.front().stop == 3 );
+	REQUIRE( v.front().value == 5.5 );
+    }
+
+    SECTION ("Point query on right") {
+	auto v = t.findOverlapping(3,3);
+	REQUIRE( v.size() == 1);
+	REQUIRE( v.front().start == 1 );
+	REQUIRE( v.front().stop == 3 );
+	REQUIRE( v.front().value == 5.5 );
+    }
+
+    SECTION ("Non-overlapping queries") {
+	REQUIRE( t.findOverlapping(4,4).size() == 0);
+	REQUIRE( t.findOverlapping(0,0).size() == 0);
+    }
+}
+
+TEST_CASE( "Two identical intervals with different contents" ) {  
+    IntervalTree<std::size_t, double> t{{{5,10,10.5},{5,10,5.5}}};
+
+    auto v = t.findOverlapping(6,6);
+    REQUIRE( v.size() == 2);
+    REQUIRE( v.front().start == 5 );
+    REQUIRE( v.front().stop == 10 );
+    REQUIRE( v.back().start == 5 );
+    REQUIRE( v.back().stop == 10 );
+    set<double> expected{5.5, 10.5};
+    set<double> actual{v.front().value, v.back().value};
+    REQUIRE( actual == expected);
+}
+
+template<typename Scalar>
+Scalar randKey(Scalar floor, Scalar ceiling) {
+    Scalar range = ceiling - floor;
+    return floor + range * ((double) rand() / (double) (RAND_MAX + 1.0));
+}
+
+template<class Scalar, typename Value>
+Interval<Scalar, Value> randomInterval(Scalar maxStart,  Scalar maxLength, Scalar maxStop, 
+                                       const Value& value) {
+    Scalar start = randKey<Scalar>(0, maxStart);
+    Scalar stop = min<Scalar>(randKey<Scalar>(start, start + maxLength), maxStop);
+    return Interval<Scalar, Value>(start, stop, value);
+}
+
+int main(int argc, char**argv) {
+    typedef vector<std::size_t> countsVector;
+
+    // a simple sanity check
+    typedef IntervalTree<int, bool> ITree;
+    ITree::interval_vector sanityIntervals;
+    sanityIntervals.push_back(ITree::interval(60, 80, true));
+    sanityIntervals.push_back(ITree::interval(20, 40, true));
+    ITree sanityTree(std::move(sanityIntervals), 16, 1);
+
+    ITree::interval_vector sanityResults;
+    sanityResults = sanityTree.findOverlapping(30, 50);
+    assert(sanityResults.size() == 1);
+
+    sanityResults = sanityTree.findContained(15, 45);
+    assert(sanityResults.size() == 1);
+
+
+    srand((unsigned)time(NULL));
+
+    ITree::interval_vector intervals;
+    ITree::interval_vector queries;
+
+    // generate a test set of target intervals
+    for (int i = 0; i < 10000; ++i) {
+        intervals.push_back(randomInterval<int, bool>(100000, 1000, 100000 + 1, true));
+    }
+    // and queries
+    for (int i = 0; i < 5000; ++i) {
+        queries.push_back(randomInterval<int, bool>(100000, 1000, 100000 + 1, true));
+    }
+
+    typedef chrono::high_resolution_clock Clock;
+    typedef chrono::milliseconds milliseconds;
+
+    // using brute-force search
+    countsVector bruteforcecounts;
+    Clock::time_point t0 = Clock::now();
+    for (auto q = queries.begin(); q != queries.end(); ++q) {
+        ITree::interval_vector results;
+        for (auto i = intervals.begin(); i != intervals.end(); ++i) {
+            if (i->start >= q->start && i->stop <= q->stop) {
+                results.push_back(*i);
+            }
+        }
+        bruteforcecounts.push_back(results.size());
+    }
+    Clock::time_point t1 = Clock::now();
+    milliseconds ms = chrono::duration_cast<milliseconds>(t1 - t0);
+    cout << "brute force:\t" << ms.count() << "ms" << endl;
+
+    // using the interval tree
+    cout << intervals[0];
+    ITree tree = ITree(std::move(intervals), 16, 1);
+    countsVector treecounts;
+    t0 = Clock::now();
+    for (auto q = queries.begin(); q != queries.end(); ++q) {
+        auto results = tree.findContained(q->start, q->stop);
+        treecounts.push_back(results.size());
+    }
+    t1 = Clock::now();
+    ms = std::chrono::duration_cast<milliseconds>(t1 - t0);
+    cout << "interval tree:\t" << ms.count() << "ms" << endl;
+
+    // check that the same number of results are returned
+    countsVector::iterator b = bruteforcecounts.begin();
+    for (countsVector::iterator t = treecounts.begin(); t != treecounts.end(); ++t, ++b) {
+        assert(*b == *t);
+    }
+
+    return Catch::Session().run( argc, argv );
+}


=====================================
multichoose/.gitignore
=====================================
@@ -0,0 +1,5 @@
+multichoose
+cmultichoose
+tad
+.*swp
+*.pyc


=====================================
multichoose/LICENSE
=====================================
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Erik Garrison
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.


=====================================
multichoose/Makefile
=====================================
@@ -0,0 +1,22 @@
+
+CC ?=	gcc
+CXX ?=	g++
+
+all: multichoose multipermute
+
+#multichoose_recursive: multichoose_recursive.cpp
+#	${CXX} multichoose_recursive.cpp -o multichoose_recursive
+
+multichoose: multichoose.cpp multichoose.h
+	${CXX} multichoose.cpp -o multichoose
+
+multipermute: multipermute.cpp multipermute.h
+	${CXX} multipermute.cpp -o multipermute
+
+cmultichoose: multichoose.c
+	${CC} multichoose.c -o cmultichoose
+
+clean:
+	rm -f cmultichoose
+	rm -f multichoose
+	rm -f multipermute


=====================================
multichoose/README.md
=====================================
@@ -0,0 +1,92 @@
+# multichoose
+
+[![NPM](https://nodei.co/npm/multichoose.png?global=true)](https://nodei.co/npm/multichoose/)
+
+[![Build Status](https://travis-ci.org/ekg/multichoose.svg)](https://travis-ci.org/ekg/multichoose)
+
+multiset combinations of k out of n (n multichoose k)
+
+## Overview
+
+This library implements an efficient loopless multiset combination generation algorithm which is (approximately) described in "Loopless algorithms for generating permutations, combinations, and other combinatorial configurations." G Ehrlich - Journal of the ACM (JACM), 1973. (Algorithm 7.)
+
+The method generates all multisets that would be generated from taking k elements from a multiset of n. Repeated multisets are possible if the input set contains repeated elements. The number of multiset combinations equals the multinomial coefficient (n multichoose k).
+
+## Usage
+
+### node.js implementation
+
+Install via
+
+``` bash
+npm install -g multichoose
+```
+
+``` js
+var multichoose = require('multichoose')
+multichoose(2, [1,2,3], console.log)
+// [ 1, 1 ]
+// [ 1, 2 ]
+// [ 1, 3 ]
+// [ 2, 2 ]
+// [ 2, 3 ]
+// [ 3, 3 ]
+```
+
+``` bash
+% multichoose 3 A B C
+A A A
+A A B
+A A C
+A B B
+A B C
+A C C
+B B B
+B B C
+B C C
+C C C
+```
+
+### multichoose.cpp
+
+Include is a C++ library/program which contains a generic function to generate multisets for vectors of any type of object.  You can test out the program using strings input from the command line by typing:
+
+``` bash
+% make
+```
+
+Running the bare executable prints usage information:
+
+``` bash
+% ./multichoose
+usage: 
+./multichoose <k> <item1> <item2> ... <itemN>  ~ n multichoose k
+```
+
+Example usage:
+
+``` bash
+% ./multichoose 2 a t g c
+a a 
+a t 
+a g 
+a c 
+t t
+t g 
+t c 
+g g 
+g c 
+c c
+```
+
+This example lists all the possible *unordered* genotypes at a given genetic loci of which there are two copies (e.g. chromosomes).  In this case `k` (=2) could be understood as the expected ploidy of the given locus..
+
+(Note that this is not currently built as the default binary for the npm module, which uses cli.js.)
+
+### multichoose.py
+
+A python library implementation is also included for those who like to indent their code consistently.
+
+## multiset permutations
+
+TODO: These will be factored into a separate module.


=====================================
multichoose/cli.js
=====================================
@@ -0,0 +1,16 @@
+#!/usr/bin/env node
+
+var multichoose = require('multichoose')
+
+if (process.argv.length < 3) {
+  console.log('usage:', process.argv[1], '<k>', '[item_1, ..., item_n] # ~ n multichoose k')
+  console.log('output the multiset combinations of size k from n items using an efficient loopless algorithm')
+  process.exit(1)
+}
+
+var k = process.argv[2]
+var objects = process.argv.slice(3, process.argv.length)
+
+multichoose(k, objects, function(x) {
+  console.log(x.join(' '))
+})


=====================================
multichoose/index.js
=====================================
@@ -0,0 +1,51 @@
+
+/*
+def multichoose(k, objects):
+    """n multichoose k multisets from the list of objects.  n is the size of
+    the objects."""
+    j,j_1,q = k,k,k  # init here for scoping
+    r = len(objects) - 1
+    a = [0 for i in range(k)] # initial multiset indexes
+    while True:
+        yield [objects[a[i]] for i in range(0,k)]  # emit result
+        j = k - 1
+        while j >= 0 and a[j] == r: j -= 1
+        if j < 0: break  # check for end condition
+        j_1 = j
+        while j_1 <= k - 1:
+            a[j_1] = a[j_1] + 1 # increment
+            q = j_1
+            while q < k - 1:
+                a[q+1] = a[q] # shift left
+                q += 1
+            q += 1
+            j_1 = q
+
+*/
+
+var range = require('range')
+
+function multichoose(k, objects, cb) {
+  var j=k,j_1=k,q=k
+  var r = objects.length - 1
+  var a = range(0,k).map(function() { return 0 })
+  while (true) {
+    cb(range(0,k).map(function(i) { return objects[a[i]] }))
+    j = k - 1
+    while (j >= 0 && a[j] == r) --j
+    if (j < 0) break
+    j_1 = j
+    while (j_1 <= k - 1) {
+      a[j_1] = a[j_1] + 1
+      var q = j_1
+      while (q < k - 1) {
+        a[q+1] = a[q]
+        ++q
+      }
+      ++q
+      j_1 = q
+    }
+  }
+}
+
+module.exports = multichoose


=====================================
multichoose/multichoose.c
=====================================
@@ -0,0 +1,53 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+
+int main(int argc, char** argv){
+
+    int *a, *b;
+    char **m;
+    int i,j,j_1,k,n,r;
+
+    if (argc<3) {
+        printf("usage: ./multi_erik k item_1 ... item_n\n");
+        return 0;
+    }
+    n = atoi(argv[1]);
+    r = argc - 2;
+
+    m = malloc(r * sizeof(char*));
+    a = malloc(n * sizeof(int));
+    b = malloc(n * sizeof(int));
+
+    for (i=2;i<argc;i++)
+        m[i-1] = argv[i];
+
+    for (i=1;i<=n;i++) {
+        a[i] = 1; b[i] = r;
+    }
+
+    j=n;
+    while(1){
+        // emit multiset combination
+        for(i=1;i<=n;i++)
+            printf("%s ", m[a[i]]);
+        printf("\n");
+        j=n;
+        while(a[j]==b[j])j--;
+        if (j<=0) break;
+        j_1=j;
+        while(j_1<=n){
+            a[j_1]=a[j_1]+1;
+            k=j_1;
+            while(k<n) {
+                a[k+1]=a[k];
+                k++;
+            }
+            k++;
+            j_1=k;
+        }
+    }
+
+    return 0;
+}
+


=====================================
multichoose/multichoose.cpp
=====================================
@@ -0,0 +1,66 @@
+/* 
+
+multichoose.cpp  -- n multichoose k for generic vectors
+
+author: Erik Garrison <erik.garrison at bc.edu>
+last revised: 2010-04-16
+
+Copyright (c) 2010 by Erik Garrison
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+ */
+
+#include <iostream>
+#include <vector>
+#include <list>
+#include <stdlib.h>
+#include "multichoose.h"
+
+
+using namespace std;
+
+
+int main(int argc, char** argv) { 
+    if (argc < 3) {
+        cerr << "usage: " << endl
+             << argv[0] << " <k> <item1> <item2> ... <itemN>  ~ n multichoose k" << endl;
+        return 1;
+    }
+
+    int k = atoi(argv[1]);
+    vector<string> items;
+    for (int i = 2; i < argc; ++i) {
+        items.push_back(string(argv[i]));
+    }
+
+    vector< vector<string> > results = multichoose(k, items);
+
+    for (vector< vector<string> >::const_iterator i = results.begin(); i != results.end(); ++i) {
+        for (vector<string>::const_iterator j = i->begin(); j != i->end(); ++j) {
+            cout << *j << " ";
+        }
+        cout << endl;
+    }
+
+    return 0; 
+}


=====================================
multichoose/multichoose.h
=====================================
@@ -0,0 +1,79 @@
+#ifndef __MULTICHOOSE_H
+#define __MULTICHOOSE_H
+
+/* 
+
+multichoose.h  -- n multichoose k for generic vectors
+
+author: Erik Garrison <erik.garrison at bc.edu>
+last revised: 2010-04-16
+
+Copyright (c) 2010 by Erik Garrison
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+
+// provides multiset combinations out of the std::vector of objects
+template <class T>
+std::vector< std::vector<T> > multichoose(int k, std::vector<T>& objects) {
+
+    std::vector< std::vector<T> > choices;
+
+    int j,j_1,q,r;
+
+    r = objects.size() - 1;
+
+    // combination indexes
+    std::vector<T*> a, b;
+
+    for (int i=0;i<k;i++) {
+        a.push_back(&objects[0]); b.push_back(&objects[r]);
+    }
+
+    j=k;
+    while(1){
+        std::vector<T> multiset;
+        for(int i=0;i<k;i++)
+            multiset.push_back(*a[i]);
+        choices.push_back(multiset);
+        j=k;
+        do { j--; } while(a[j]==b[j]);
+        if (j<0) break;
+        j_1=j;
+        while(j_1<=k-1){
+            a[j_1]=a[j_1]+1;
+            q=j_1;
+            while(q<k-1) {
+                a[q+1]=a[q];
+                q++;
+            }
+            q++;
+            j_1=q;
+        }
+    }
+    
+    return choices;
+}
+
+#endif


=====================================
multichoose/multichoose.py
=====================================
@@ -0,0 +1,55 @@
+# encoding: utf-8
+
+"""
+
+multichoose.py  -- non-recursive n multichoose k for python lists
+
+author: Erik Garrison <erik.garrison at bc.edu>
+last revised: 2010-04-30
+
+Copyright (c) 2010 by Erik Garrison
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+"""
+
+def multichoose(k, objects):
+    """n multichoose k multisets from the list of objects.  n is the size of
+    the objects."""
+    j,j_1,q = k,k,k  # init here for scoping
+    r = len(objects) - 1
+    a = [0 for i in range(k)] # initial multiset indexes
+    while True:
+        yield [objects[a[i]] for i in range(0,k)]  # emit result
+        j = k - 1
+        while j >= 0 and a[j] == r: j -= 1
+        if j < 0: break  # check for end condition
+        j_1 = j
+        while j_1 <= k - 1:
+            a[j_1] = a[j_1] + 1 # increment
+            q = j_1
+            while q < k - 1:
+                a[q+1] = a[q] # shift left
+                q += 1
+            q += 1
+            j_1 = q
+


=====================================
multichoose/multipermute.cpp
=====================================
@@ -0,0 +1,66 @@
+/* 
+
+multipermute.cpp  -- multiset permutations for generic vectors
+
+author: Erik Garrison <erik.garrison at bc.edu>
+last revised: 2010-06-02
+
+Copyright (c) 2010 by Erik Garrison
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+
+#include <iostream>
+#include <vector>
+#include <list>
+#include <stdlib.h>
+#include "multipermute.h"
+
+
+using namespace std;
+
+
+int main(int argc, char** argv) { 
+    if (argc < 3) {
+        cerr << "usage: " << endl
+             << argv[0] << " [multiset, items delimited by space]  ~ multiset permutations of " << endl;
+        return 1;
+    }
+
+    vector<string> items;
+    for (int i = 1; i < argc; ++i) {
+        items.push_back(string(argv[i]));
+    }
+
+    vector< vector<string> > results = multipermute(items);
+
+    for (vector< vector<string> >::const_iterator i = results.begin(); i != results.end(); ++i) {
+        for (vector<string>::const_iterator j = i->begin(); j != i->end(); ++j) {
+            cout << *j << " ";
+        }
+        cout << endl;
+    }
+
+    return 0; 
+}


=====================================
multichoose/multipermute.h
=====================================
@@ -0,0 +1,132 @@
+/* 
+
+multipermute.h  -- multiset permutations for generic vectors
+
+Follows 'Algorithm 1' from "Loopless Generation of Multiset Permutations using
+a Constant Number of Variables by Prefix Shifts."  Aaron Williams, 2009
+
+author: Erik Garrison <erik.garrison at bc.edu>
+last revised: 2010-04-16
+
+Copyright (c) 2010 by Erik Garrison
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+
+#include <vector>
+#include <algorithm>
+
+template <class T>
+class ListElement { 
+
+public:
+    T value;
+    ListElement<T>* next;
+
+    ListElement<T>() { }
+
+    ListElement<T>(T val, ListElement<T>* n) {
+        value = val;
+        next = n;
+    }
+
+    ListElement<T>* nth(int n) {
+        ListElement<T>* o = this;
+        int i = 0;
+        while (i < n && o->next != NULL) {
+            o = o->next;
+            ++i;
+        }
+        return o;
+    }
+
+    ~ListElement<T>() {
+        if (next != NULL) {
+            delete next;
+        }
+    }
+
+};
+
+template <class T>
+ListElement<T>* list_init(std::vector<T>& multiset) {
+    std::sort(multiset.begin(), multiset.end()); // ensures proper non-increasing order
+    typename std::vector<T>::const_iterator item = multiset.begin();
+    ListElement<T>* h = new ListElement<T>(*item, NULL);
+    ++item;
+    while (item != multiset.end()) {
+        h = new ListElement<T>(*item, h);
+        ++item;
+    }
+    return h;
+}
+
+template <class T>
+std::vector<T> linked_list_to_vector(ListElement<T>* h) {
+    ListElement<T>* o = h;
+    std::vector<T> l;
+    while (o != NULL) {
+        l.push_back(o->value);
+        o = o->next;
+    }
+    return l;
+}
+
+// provides multiset permutations out of the std::vector multiset
+template <class T>
+std::vector< std::vector<T> > multipermute(std::vector<T>& multiset) {
+
+    std::vector< std::vector<T> > results;
+
+    ListElement<T>* h = list_init(multiset);
+    ListElement<T>* i = h->nth(multiset.size() - 2);
+    ListElement<T>* j = h->nth(multiset.size() - 1);
+    ListElement<T>* s;
+    ListElement<T>* t;
+
+    results.push_back(linked_list_to_vector(h));
+
+    while (j->next != NULL || j->value < h->value) {
+        if (j->next != NULL && i->value >= j->next->value) {
+            s = j;
+        } else {
+            s = i;
+        }
+        t = s->next;
+        s->next = t->next;
+        t->next = h;
+        if (t->value < h->value) {
+            i = t;
+        }
+        j = i->next;
+        h = t;
+        results.push_back(linked_list_to_vector(h));
+    }
+
+    delete h;
+
+    return results;
+
+}
+


=====================================
multichoose/multipermute.py
=====================================
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# multipermute.py - permutations of a multiset
+# Erik Garrison <erik.garrison at bc.edu> 2010
+
+"""
+This module encodes functions to generate the permutations of a multiset
+following this algorithm:
+
+Algorithm 1 
+Visits the permutations of multiset E. The permutations are stored
+in a singly-linked list pointed to by head pointer h. Each node in the linked
+list has a value field v and a next field n. The init(E) call creates a
+singly-linked list storing the elements of E in non-increasing order with h, i,
+and j pointing to its first, second-last, and last nodes, respectively. The
+null pointer is given by φ. Note: If E is empty, then init(E) should exit.
+Also, if E contains only one element, then init(E) does not need to provide a
+value for i.
+
+[h, i, j] ← init(E) 
+visit(h) 
+while j.n ≠ φ orj.v <h.v do
+    if j.n ≠    φ and i.v ≥ j.n.v then 
+        s←j
+    else
+        s←i 
+    end if
+    t←s.n 
+    s.n ← t.n 
+    t.n ← h 
+    if t.v < h.v then
+        i←t 
+    end if
+    j←i.n 
+    h←t 
+    visit(h)
+end while
+
+... from "Loopless Generation of Multiset Permutations using a Constant Number
+of Variables by Prefix Shifts."  Aaron Williams, 2009
+"""
+
+class ListElement:
+    def __init__(self, value, next):
+        self.value = value
+        self.next = next
+    def nth(self, n):
+        o = self
+        i = 0
+        while i < n and o.next is not None:
+            o = o.next
+            i += 1
+        return o
+
+def init(multiset):
+    multiset.sort() # ensures proper non-increasing order
+    h = ListElement(multiset[0], None)
+    for item in multiset[1:]:
+        h = ListElement(item, h)
+    return h, h.nth(len(multiset) - 2), h.nth(len(multiset) - 1)
+
+def visit(h):
+    """Converts our bespoke linked list to a python list."""
+    o = h
+    l = []
+    while o is not None:
+        l.append(o.value)
+        o = o.next
+    return l
+
+def permutations(multiset):
+    """Generator providing all multiset permutations of a multiset."""
+    h, i, j = init(multiset)
+    yield visit(h)
+    while j.next is not None or j.value < h.value:
+        if j.next is not None and i.value >= j.next.value:
+            s = j
+        else:
+            s = i
+        t = s.next
+        s.next = t.next
+        t.next = h
+        if t.value < h.value:
+            i = t
+        j = i.next
+        h = t
+        yield visit(h)
+
+if __name__ == '__main__':
+    import sys
+    multiset = sys.argv[1:]
+    if multiset != []:
+        for permutation in permutations(multiset):
+            for item in permutation:
+                print item,
+            print
+    else:
+        print "usage", sys.argv[0], "<multiset>"


=====================================
multichoose/package.json
=====================================
@@ -0,0 +1,34 @@
+{
+  "name": "multichoose",
+  "version": "1.0.3",
+  "description": "generate multiset combinations using an efficient loopless algorithm",
+  "main": "index.js",
+  "scripts": {
+    "test": "node test.js | tap-spec"
+  },
+  "bin": {
+    "multichoose": "cli.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/ekg/multichoose.git"
+  },
+  "keywords": [
+    "multiset",
+    "combinations",
+    "multichoose",
+    "combinatorics",
+    "math"
+  ],
+  "author": "Erik Garrison",
+  "license": "MIT",
+  "readmeFilename": "README.md",
+  "gitHead": "0d5c4079a071cc15993f2c8d9e3081dff9a1ce0d",
+  "dependencies": {
+    "range": "0.0.2"
+  },
+  "devDependencies": {
+    "tap-spec": "^2.1.1",
+    "tape": "^3.0.3"
+  }
+}


=====================================
multichoose/test.js
=====================================
@@ -0,0 +1,66 @@
+var test = require('tape')
+var multichoose = require('./')
+
+test('multichoose test', function (t) {
+
+  t.plan(2)
+
+  var c = [ [ 1, 1 ],
+            [ 1, 2 ],
+            [ 1, 3 ],
+            [ 2, 2 ],
+            [ 2, 3 ],
+            [ 3, 3 ] ]
+
+  var r = []
+  multichoose(2, [1,2,3],
+              function(x) {
+                r.push(x)
+              })
+
+  t.deepEqual(c, r)
+
+  c = [ [ 0, 0, 0 ],
+        [ 0, 0, 1 ],
+        [ 0, 0, 2 ],
+        [ 0, 0, 3 ],
+        [ 0, 0, 4 ],
+        [ 0, 1, 1 ],
+        [ 0, 1, 2 ],
+        [ 0, 1, 3 ],
+        [ 0, 1, 4 ],
+        [ 0, 2, 2 ],
+        [ 0, 2, 3 ],
+        [ 0, 2, 4 ],
+        [ 0, 3, 3 ],
+        [ 0, 3, 4 ],
+        [ 0, 4, 4 ],
+        [ 1, 1, 1 ],
+        [ 1, 1, 2 ],
+        [ 1, 1, 3 ],
+        [ 1, 1, 4 ],
+        [ 1, 2, 2 ],
+        [ 1, 2, 3 ],
+        [ 1, 2, 4 ],
+        [ 1, 3, 3 ],
+        [ 1, 3, 4 ],
+        [ 1, 4, 4 ],
+        [ 2, 2, 2 ],
+        [ 2, 2, 3 ],
+        [ 2, 2, 4 ],
+        [ 2, 3, 3 ],
+        [ 2, 3, 4 ],
+        [ 2, 4, 4 ],
+        [ 3, 3, 3 ],
+        [ 3, 3, 4 ],
+        [ 3, 4, 4 ],
+        [ 4, 4, 4 ] ]
+
+  r = []
+  multichoose(3, [0,1,2,3,4],
+              function(x) {
+                r.push(x)
+              })
+  t.deepEqual(c, r)
+
+});



View it on GitLab: https://salsa.debian.org/med-team/libvcflib/-/commit/5623aeddbf6ca2e5ae7e9107e53d7cca72f1670f

-- 
View it on GitLab: https://salsa.debian.org/med-team/libvcflib/-/commit/5623aeddbf6ca2e5ae7e9107e53d7cca72f1670f
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20220220/76241ea8/attachment-0001.htm>


More information about the debian-med-commit mailing list