[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
+
+[](https://nodei.co/npm/multichoose/)
+
+[](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