From 16ded8a59c300b3702c396e71897662e0a196b8c Mon Sep 17 00:00:00 2001 From: Nikos M Date: Fri, 1 Jul 2016 01:00:08 +0300 Subject: [PATCH] updates, in progress --- README.md | 26 +- src/js/Abacus.js | 2700 ++++++++++++++++++--------------- src/js/Abacus.min.js | 2 +- test/biginteger/arithmetic.js | 51 +- test/combinations.js | 51 +- test/combinations.txt | 94 +- test/combinations_repeats.js | 54 +- test/combinations_repeats.txt | 230 ++- test/partitions.js | 21 +- test/permutations-bigint.txt | 78 +- test/permutations.js | 54 +- test/permutations.txt | 150 +- test/subsets.js | 52 +- test/subsets.txt | 119 +- test/tensors.js | 51 +- test/tensors.txt | 52 +- test/test.bat | 4 +- test/tuples.js | 51 +- test/tuples.txt | 137 +- 19 files changed, 2354 insertions(+), 1623 deletions(-) diff --git a/README.md b/README.md index 2269d87..4b209a2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Abacus -A combinatorics library for Node/JS, PHP, Python, ActionScript +A combinatorics library for Node/XPCOM/JS, PHP, Python, ActionScript **update in progress do not use** @@ -111,7 +111,7 @@ o.forward() [ 0, 1, 4 ] [ 0, 1, 3 ] [ 0, 1, 2 ] -o.order("revlex") +o.order("lex,reversed") [ 3, 4, 5 ] [ 2, 4, 5 ] [ 2, 3, 5 ] @@ -153,7 +153,7 @@ o.order("colex") [ 1, 4, 5 ] [ 2, 4, 5 ] [ 3, 4, 5 ] -o.order("revcolex") +o.order("colex,reversed") [ 3, 4, 5 ] [ 2, 4, 5 ] [ 1, 4, 5 ] @@ -174,8 +174,6 @@ o.order("revcolex") [ 0, 2, 3 ] [ 0, 1, 3 ] [ 0, 1, 2 ] -o.random() -[ 1, 3, 5 ] o.order("random") [ 0, 1, 3 ] [ 1, 4, 5 ] @@ -197,6 +195,8 @@ o.order("random") [ 0, 1, 4 ] [ 0, 3, 4 ] [ 1, 3, 4 ] +o.random() +[ 1, 3, 5 ] o.order("colex").range(-5, -1) [ [ 2, 3, 5 ], [ 0, 4, 5 ], [ 1, 4, 5 ], [ 2, 4, 5 ], [ 3, 4, 5 ] ] o.dispose() @@ -273,7 +273,7 @@ most algorithms: * are **linear** `O(n)` (or log-linear `O(nlgn)`) **time and space** algorithms * are **statisticaly unbiased** (e.g uniform sampling methods) -* use **efficient successor methods** (e.g loopless methods / constant delay methods) to generate next/prev object from current object (supporting multiple combinatorial orderings along the way, see below) +* use **efficient successor methods** (e.g loopless, constant delay methods) to generate next/prev object from current object (supporting multiple combinatorial orderings along the way, see below) * **avoid big-integer arithmetic and computational overhead** (except if explicit ranking / unranking is needed and objects are large) * arithmetic routines are **pluggable** so biginteger arithmetic can be used via external implementations. **Note** that the lib can generate **very large** (and in most cases also **randomised**) combinatorial objects **without ever using** biginteger arithmetic due to design and implementation except if arbitrary random, ranking and unranking have to be used (see above) @@ -281,13 +281,13 @@ most algorithms: ###Todo -* support **multiple custom iterator orderings**, i.e `LEX`, `COLEX`, `REVLEX`, `REVCOLEX`, `MINIMAL`, `RANDOM`, `STOCHASTIC` (where applicable) seamlessly and uniformly, both forward and backward [ALMOST DONE, NEW FEATURE] -* support **efficient ranking / unranking algorithms** and associated methods (preferably of `O(n)` or `O(nlgn)` complexity) for supported orderings [DONE] -* support **unique and uniform random ordering traversals** for all combinatorial objects, so that the space of a combinatorial object can be traversed in any random ordering uniquely and unbiasedly (useful in some applications, eg backtracking) [DONE, see reference, used as custom iterator ordering, see above] -* make sure the `.random` methods **uniformly and unbiasedly sample the combinatorial object space** (methods use unbiased sampling algorithms, however results in certain cases might depend on [quality of PRNGs](http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf)) [DONE] +* apply built-in language `iterator`/`iterable` patterns (e.g ES6 `iterator` protocol, Python `__iter__` interface, PHP `Iterator` interface, ..). Combinatorial objects additionaly support a `doubly-linked list`-like interface, i.e `prev`/`next` accessors [DONE] * support `biginteger` computations e.g factorials?? [DONE, the lib does not support biginteger arithmetic, but arithmetic routines have been made dynamicaly pluggable and one can use an external implementation to support combinatorics with bigintegers where needed as needed, see test examples for an example] -* add `Combinadic`, `Factoradic` transformations [DONE] -* add magic squares algorithms [IN PROGRESS, NEW FEATURE] -* add `Derangement`, `RestrictedPartition` [IN PROGRESS] +* support **multiple combined custom iterator orderings**, i.e `lex`, `colex`, `reversed`, `reflected`, `minimal/gray`, `random`, `stochastic` (where applicable) seamlessly and uniformly, both forward and backward [ALMOST DONE, NEW FEATURE] +* support **efficient ranking / unranking algorithms** and associated methods (preferably of `O(n)` or `O(nlgn)` complexity) for supported orderings [ALMOST DONE] +* make sure the `.random` methods **uniformly and unbiasedly sample the combinatorial object space** (methods use unbiased sampling algorithms, however results in certain cases might depend on [quality of PRNGs](http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf)) [DONE] +* support **unique and uniform random ordering traversals** for all combinatorial objects, so that the space of a combinatorial object can be traversed in **any random ordering uniquely and unbiasedly** (useful in some applications, eg backtracking) [ALMOST DONE, see reference, used as custom iterator ordering, see above] +* add `MultisetPermutation`, `Derangement`, `SetPartition`, `RestrictedPartition` [IN PROGRESS] +* add latin squares, magic squares algorithms [IN PROGRESS] * support generation of combinatorial objects based on *patterns/templates of constraints* to satisfy e.g "only combinations with `xx(n)(n+1)x`" pattern and so on.. (TODO) * add generic *rule-based* `Combinatorial` objects like `Grammar` (TODO) diff --git a/src/js/Abacus.js b/src/js/Abacus.js index 676fb7b..dbe6599 100644 --- a/src/js/Abacus.js +++ b/src/js/Abacus.js @@ -23,7 +23,8 @@ else if ( !(name in root) ) /* Browser/WebWorker/.. */ var Abacus = {VERSION: "0.1.0"} ,PROTO = 'prototype', CLASS = 'constructor', HAS = 'hasOwnProperty' - ,slice = Array.prototype.slice + ,NotImplemented = function( ) { throw new Error("Method not implemented!"); } + ,slice = Array.prototype.slice, toString = Object[PROTO].toString ,Extend = Object.create ,Merge = function(a, b) { for (var p in b) if (b[HAS](p)) a[p] = b[p]; @@ -149,66 +150,6 @@ var Abacus = {VERSION: "0.1.0"} } return Fx; } - ,intersection = function intersect_sorted2( a, b ) { - var ai = 0, bi = 0, intersection = [ ], - al = a.length, bl = b.length; - // assume a, b lists are sorted ascending - while( ai < al && bi < bl ) - { - if ( a[ai] < b[bi] ) - { - ai++; - } - else if ( a[ai] > b[bi] ) - { - bi++; - } - else // they're equal - { - intersection.push( a[ ai ] ); - ai++; bi++; - } - } - return intersection; - } - ,union = function merge_sorted2( a, b, unique ) { - var ai = 0, bi = 0, merged = [ ], last, - al = a.length, bl = b.length, with_duplicates; - unique = false !== unique; - with_duplicates = !unique; - // assume a, b lists are sorted ascending, even with duplicate values - while( ai < al && bi < bl ) - { - if (unique && merged.length) // handle any possible duplicates inside SAME list - { - if (a[ai] === last) - { - ai++; continue; - } - else if (b[bi] === last) - { - bi++; continue; - } - } - if ( a[ai] < b[bi] ) - { - merged.push( last=a[ai++] ); - } - else if ( a[ai] > b[bi] ) - { - merged.push( last=b[bi++] ); - } - else // they're equal, push one unique - { - merged.push( last=a[ ai ] ); - if ( with_duplicates ) merged.push( b[ bi ] ); - ai++; bi++; - } - } - while ( ai < al ) if (with_duplicates || (a[ai] !== last)) merged.push( last=a[ai++] ); - while ( bi < bl ) if (with_duplicates || (b[bi] !== last)) merged.push( last=b[bi++] ); - return merged; - } ,kronecker = function kronecker( /* var args here */ ) { var k, a, r, l, i, j, vv, tensor, v = arguments, nv = v.length, @@ -278,18 +219,128 @@ var Abacus = {VERSION: "0.1.0"} } return product; } + ,intersect = function intersect_sorted2( a, b, reverse ) { + reverse = -1 === reverse ? 1 : 0; + var ai = 0, bi = 0, al = a.length, bl = b.length, + intersection = new Array(Abacus.Math.min(al,bl)), il = 0; + // assume a, b lists are sorted ascending/descending depending on reverse flag + while( (ai < al) && (bi < bl) ) + { + if ( a[ai] < b[bi] ) + { + if ( reverse ) bi++; else ai++; + } + else if ( a[ai] > b[bi] ) + { + if ( reverse ) ai++; else bi++; + } + else // they're equal + { + intersection[il++] = a[ ai ]; + ai++; bi++; + } + } + // truncate if needed + if ( il < intersection.length ) intersection.length = il; + return intersection; + } + ,merge = function merge_sorted2( a, b, reverse, unique ) { + reverse = -1 === reverse ? 1 : 0; unique = false !== unique; + var ai = 0, bi = 0, al = a.length, bl = b.length, + union = new Array(al+bl), ul = 0, last, with_duplicates = !unique; + // assume a, b lists are sorted ascending, even with duplicate values + while( ai < al && bi < bl ) + { + if (unique && ul) // handle any possible duplicates inside SAME list + { + if ( a[ai] === last ) + { + ai++; + continue; + } + else if ( b[bi] === last ) + { + bi++; + continue; + } + } + if ( a[ai] < b[bi] ) + { + union[ul++] = last = reverse?b[bi++]:a[ai++]; + } + else if ( a[ai] > b[bi] ) + { + union[ul++] = last = reverse?a[ai++]:b[bi++]; + } + else // they're equal, push one unique + { + union[ul++] = last = a[ ai ]; + if ( with_duplicates ) union[ul++] = b[ bi ]; + ai++; bi++; + } + } + while ( ai < al ) if ( with_duplicates || (a[ai] !== last) ) union[ul++] = last = a[ai++]; + while ( bi < bl ) if ( with_duplicates || (b[bi] !== last) ) union[ul++] = last = b[bi++]; + // truncate if needed + if ( ul < union.length ) union.length = ul; + return union; + } + ,insert_sort = function insert_sorted2( a, v, k, reverse ) { + reverse = -1 === reverse ? 1 : 0; + // assume list a is ALREADY SORTED ASC/DESC, depending on reverse flag + if ( null == k ) k = v; + var l = a.length, s, m, e; + if ( 0 === l ) + { + a.push( v ); + } + else if ( k < a[reverse ? l-1 : 0] ) + { + if ( reverse ) a.push( v ); else a.unshift( v ); + } + else if ( k >= a[reverse ? 0 : l-1] ) + { + if ( reverse ) a.unshift( v ); else a.push( v ); + } + else + { + // insert sorted using binary search + // O(logN) worst-case time + s = 0; e = l-1; + if ( reverse ) + { + while ( e > s ) + { + m = s + ((e-s+1)>>>1); + if ( k < a[ m ] ) s = m; + else e = m-1; + } + } + else + { + while ( e > s ) + { + m = s + ((e-s+1)>>>1); + if ( k < a[ m ] ) e = m-1; + else s = m; + } + } + if ( k < a[ s ] ) a.splice(reverse ? s+1 : s, 0, v); + else a.splice(reverse ? s : s+1, 0, v); + } + return a; + } ,shuffle = function shuffle( a, cyclic, copied ) { // http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle // https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Sattolo.27s_algorithm - var rnd = Abacus.Util.rint, + var rndInt = Abacus.Math.rndInt, N, perm, swap, ac, offset; ac = true === copied ? a.slice() : a; offset = true === cyclic ? 1 : 0; N = ac.length; while ( offset < N-- ) { - perm = rnd( 0, N-offset ); - if ( N === perm ) continue; + perm = rndInt( 0, N-offset ); swap = ac[ N ]; ac[ N ] = ac[ perm ]; ac[ perm ] = swap; @@ -297,25 +348,122 @@ var Abacus = {VERSION: "0.1.0"} // in-place or copy return ac; } - ,pick = function pick( a, k, non_destructive ) { + ,compl = function compl( exc, N ) { + var inc = [], i=0, j=0, n = excl.length; + while (i < N) + { + if (j>=n || i= k) || (n < alpha[a]) ) + for(i=k-1; i>=0; i--) { - beta[b++] = n; + g[i] = n[i] > 0 ? (a[i] + shft) % n[i] : 0; + shft = shft + n[i] - g[i]; } - else + } + else + { + for(i=k-1; i>=0; i--) { - a++; + // The gray digit gets shifted down by the sum of the higher + // digits. + g[i] = (a[i] + shft) % n; + shft = shft + n - g[i]; // Subtract from base so shift is positive } - n++; } - return beta; + return g; } else { - if ( !alpha.length ) return []; - var i, k = alpha.length, beta = new Array(k); - if ( true === dim_array ) for (i=0; i= k) || (i < a[ai]) ) + { + b[bi++] = i; + } + else + { + ai++; + } + i++; + } + return b; } - ,cycle2swaps = function( cycle ) { - var swaps = [], c = cycle.length, j; - if ( c > 1 ) for (j=c-1; j>=1; j--) swaps.push([cycle[0],cycle[j]]) - return swaps; + ,conjugate_partition = function conjugate_partition( a ) { + if ( null == a ) return null; + // http://mathworld.wolfram.com/ConjugatePartition.html + var l = a.length, n = a[0], i, j, p, b = new Array(n); + for (i=0; i 0 ) + { + b[i++]++; + p--; + } + } + return b; } - ,partition2cycles = function( partition ) { - var cycles = [], cycle, i, - pi, pl = partition.length, p, - current = 0; - for (pi=0; pi 1 ) for (j=c-1; j>=1; j--) swaps.push([cycle[0],cycle[j]]) + return swaps; } ,sum = function sum( a ) { - var add = Abacus.Arithmetic.add; - return operate(a, add, 0); + return operate(a, Abacus.Arithmetic.add, Abacus.Arithmetic.O); } - ,prod = function prod( a ) { - var mul = Abacus.Arithmetic.mul; - return operate(a, mul, 1); + ,product = function product( a ) { + return operate(a, Abacus.Arithmetic.mul, Abacus.Arithmetic.I); } ,pow2 = function pow2( n ) { - return Abacus.Arithmetic.shl(1, /*Abacus.Arithmetic.num(*/ n /*)*/);//(1 << n)>>>0; + var Arithmetic = Abacus.Arithmetic; + return Arithmetic.shl(Arithmetic.I, Arithmetic.N( n ));//(1 << n)>>>0; } - ,powNK = function powNK( n, k ) { - return Abacus.Arithmetic.pow(/*Abacus.Arithmetic.num(*/ n /*)*/, /*Abacus.Arithmetic.num(*/ k /*)*/); + ,exp = function exp( n, k ) { + var Arithmetic = Abacus.Arithmetic; + return Arithmetic.pow(Arithmetic.N( n ), Arithmetic.N( k )); } ,factorial = function factorial( n ) { - //n = Abacus.Arithmetic.num( n ); - var mul = Abacus.Arithmetic.mul; - if ( 0 > n ) return 0; - else if ( 2 > n ) return 1; + // http://www.luschny.de/math/factorial/index.html + var Arithmetic = Abacus.Arithmetic, O = Arithmetic.O, I = Arithmetic.I; + n = Arithmetic.N( n ); + if ( Arithmetic.lt( n, 0 ) ) return O; + else if ( Arithmetic.lt( n, 2 ) ) return I; // 2=>2 or 3=>6 - else if ( 4 > n ) return n<<(n-2); - else return operation(mul, 1, 2, n); + else if ( Arithmetic.lt( n, 4 ) ) return Arithmetic.shl( n, Arithmetic.sub( n, 2 ) )/*n<<(n-2)*/; + return operation(Arithmetic.mul, I, 2, n); } ,binomial = function binomial( n, k ) { - //n = Abacus.Arithmetic.num( n ); - //k = Abacus.Arithmetic.num( k ); - if ( k > n-k ) k = n-k; // take advantage of symmetry - if ( 0 > k || 1 > n ) return 0; - else if ( 0 === k || 1 === n ) return 1; + var Arithmetic = Abacus.Arithmetic, O = Arithmetic.O, I = Arithmetic.I; + if ( k > n-k ) k = n-k; // take advantage of symmetry + if ( 0 > k || 1 > n ) return O; + else if ( 0 === k || 1 === n ) return I; else if ( 1 === k ) return n; - else - { - var mul = Abacus.Arithmetic.mul, - n_k = n-k, Cnk = 1 + n_k, i; - //for (i=2; i<=k; i++) Cnk *= 1 + n_k/i; - for (i=2; i<=k; i++) Cnk = mul(Cnk, 1+n_k/i); - return Abacus.Arithmetic.round( Cnk ); - } - } - ,partitions = function partitions( n, k, m, tbl ) { + var mul = Arithmetic.mul, n_k = n-k, Cnk = Arithmetic.N( 1+n_k ), i; + //for (i=2; i<=k; i++) Cnk *= 1 + n_k/i; + for (i=2; i<=k; i++) Cnk = mul(Cnk, 1+n_k/i); + return Arithmetic.round( Cnk ); + } + ,multinomial = function multinomial( args/*var args here*/ ) { + var Arithmetic = Abacus.Arithmetic, factorial = Abacus.Math.Factorial, + m = args instanceof Array ? args : arguments, + N = factorial( m[0] ), l = m.length, k, Nk = Arithmetic.I, + mul = Arithmetic.mul, div = Arithmetic.div; + for(k=1; kn+1 || k*mn+1 || k*m 0 ? order : LEX; + } + return ORDERINGS & o ? o : LEX; } + ,CombinatorialIterator + ,Permutation//, Derangement//, MultisetPermutation + ,Combination//, CombinationRepeat + ,Partition//, RestrictedPartition//, SetPartition + ,Subset + ,Tensor, Tuple ; // combinatorial objects iterator ordering patterns @@ -480,16 +722,26 @@ Abacus.ORDER = { LEX: LEX ,LEXICOGRAPHIC: LEX -,REVLEX: REVLEX -,ANTILEX: REVLEX -,REVERSELEXICOGRAPHIC: REVLEX -,ANTILEXICOGRAPHIC: REVLEX +,REVLEX: LEX | REVERSED +,ANTILEX: LEX | REVERSED +,REVERSELEXICOGRAPHIC: LEX | REVERSED +,ANTILEXICOGRAPHIC: LEX | REVERSED +,REFLEX: LEX | REFLECTED +,REFLECTEDLEXICOGRAPHIC: LEX | REFLECTED ,COLEX: COLEX ,COLEXICOGRAPHIC: COLEX -,REVCOLEX: REVCOLEX -,ANTICOLEX: REVCOLEX -,REVERSECOLEXICOGRAPHIC: REVCOLEX -,ANTICOLEXICOGRAPHIC: REVCOLEX +,REVCOLEX: COLEX | REVERSED +,ANTICOLEX: COLEX | REVERSED +,REVERSECOLEXICOGRAPHIC: COLEX | REVERSED +,ANTICOLEXICOGRAPHIC: COLEX | REVERSED +,REFCOLEX: COLEX | REFLECTED +,REFLECTEDCOLEXICOGRAPHIC: COLEX | REFLECTED +,REV: REVERSED +,REVERSE: REVERSED +,REVERSED: REVERSED +,REF: REFLECTED +,REFLECT: REFLECTED +,REFLECTED: REFLECTED ,GRAY: MINIMAL ,MINIMAL: MINIMAL ,RANDOM: RANDOM @@ -498,24 +750,41 @@ Abacus.ORDER = { }; -Abacus.Util = { +// list/array utiltities +Abacus.List = { - rnd: Math.random -,rint: function( m, M ) { return Abacus.Arithmetic.round( (M-m)*Abacus.Util.rnd( ) + m ); } + operate: operate +,map: map +,operation: operation -,shuffle: shuffle -,pick: pick +,sum: sum +,product: product -,operate: operate -,operation: operation -,map: map -,intersection: intersection -,union: union ,kronecker: kronecker ,cartesian: cartesian -,num: function( a ) { return parseInt(a,10); } -,val: function( a ) { return Abacus.Arithmetic.floor(a.valueOf()); } +,intersection: intersect +,union: merge +,insertion: insert_sort + +,shuffle: shuffle +,xshuffle: xshuffle +,multiset_shuffle: multiset_shuffle +,pick: pick + +}; + +// math/rnd utilities +Abacus.Math = { + + O: 0 +,I: 1 + +,N: function( a ) { return Abacus.Arithmetic.add(Abacus.Arithmetic.O, a); } +,V: function( a ){ return Abacus.Arithmetic.sub(Abacus.Arithmetic.O, a); } + +,rnd: Math.random +,rndInt: function( m, M ) { return Abacus.Math.round( (M-m)*Abacus.Math.rnd( ) + m ); } ,equ: function( a, b ) { return a===b; } ,gte: function( a, b ) { return a>=b; } @@ -523,10 +792,15 @@ Abacus.Util = { ,gt: function( a, b ) { return a>b; } ,lt: function( a, b ) { return a= m) && (a <= M) : (a > m) && (a < M); } +,clamp: function( a, m, M ) { return a < m ? m : (a > M ? M : a); } +,wrap: function( a, m, M ) { return a < m ? M : (a > M ? m : a); } +,wrapR: function( a, M ) { return a < 0 ? a+M : a; } + ,add: function( a, b ) { return a+b; } ,sub: function( a, b ){ return a-b; } ,mul: function( a, b ) { return a*b; } -,div: function( a, b ){ return Abacus.Arithmetic.floor(a/b); } +,div: function( a, b ){ return Abacus.Math.floor(a/b); } ,mod: function( a, b ){ return a % b; } ,pow: Math.pow @@ -534,8 +808,8 @@ Abacus.Util = { ,shr: function( a, b ){ return a >> b; } ,bor: function( a, b ){ return a | b; } ,band: function( a, b ){ return a & b; } +,xor: function( a, b ){ return a ^ b; } -,neg: function( a ){ return Abacus.Arithmetic.sub(0, a); } ,abs: Math.abs ,min: Math.min ,max: Math.max @@ -543,48 +817,60 @@ Abacus.Util = { ,ceil: Math.ceil ,round: Math.round -,sum: sum -,product: prod -,pow2: pow2 -,powNK: powNK -,factorial: factorial -,binomial: binomial -,partitions: partitions +,num: function( a ) { return "number" === typeof a ? Abacus.Math.floor(a) : parseInt(a,10); } +,val: function( a ) { return Abacus.Math.floor(a.valueOf()); } + +,Pow2: pow2 +,Exp: exp +,Factorial: factorial +,Binomial: binomial +,Multinomial: multinomial +,Partitions: partitions }; // support pluggable arithmetics, eg biginteger Arithmetic Abacus.Arithmetic = { - num: Abacus.Util.num -,val: Abacus.Util.val + O: 0 +,I: 1 +,N: Abacus.Math.N +,V: Abacus.Math.V + +,equ: Abacus.Math.equ +,gte: Abacus.Math.gte +,lte: Abacus.Math.lte +,gt: Abacus.Math.gt +,lt: Abacus.Math.lt -,equ: Abacus.Util.equ -,gte: Abacus.Util.gte -,lte: Abacus.Util.lte -,gt: Abacus.Util.gt -,lt: Abacus.Util.lt +,inside: Abacus.Math.inside +,clamp: Abacus.Math.clamp +,wrap: Abacus.Math.wrap +,wrapR: Abacus.Math.wrapR -,add: Abacus.Util.add -,sub: Abacus.Util.sub -,mul: Abacus.Util.mul -,div: Abacus.Util.div -,mod: Abacus.Util.mod -,pow: Abacus.Util.pow +,add: Abacus.Math.add +,sub: Abacus.Math.sub +,mul: Abacus.Math.mul +,div: Abacus.Math.div +,mod: Abacus.Math.mod +,pow: Abacus.Math.pow -,shl: Abacus.Util.shl -,shr: Abacus.Util.shr -,bor: Abacus.Util.bor -,band: Abacus.Util.band +,shl: Abacus.Math.shl +,shr: Abacus.Math.shr +,bor: Abacus.Math.bor +,band: Abacus.Math.band +,xor: Abacus.Math.xor -,neg: Abacus.Util.neg -,abs: Abacus.Util.abs -,min: Abacus.Util.min -,max: Abacus.Util.max -,floor: Abacus.Util.floor -,ceil: Abacus.Util.ceil -,round: Abacus.Util.round -,rnd: Abacus.Util.rint +,abs: Abacus.Math.abs +,min: Abacus.Math.min +,max: Abacus.Math.max +,floor: Abacus.Math.floor +,ceil: Abacus.Math.ceil +,round: Abacus.Math.round +,rnd: Abacus.Math.rndInt + +,num: Abacus.Math.num +,val: Abacus.Math.val }; @@ -594,7 +880,7 @@ Abacus.BitArray = Class({ var self = this; if ( !(self instanceof BitArray) ) return new BitArray(n); self.length = n; - self.bits = new Uint32Array( Abacus.Arithmetic.ceil(n/32) ); + self.bits = new Uint32Array( Abacus.Math.ceil(n/32) ); } ,length: 0 @@ -656,50 +942,56 @@ Abacus.BitArray = Class({ } }); + // Abacus.CombinatorialIterator, Combinatorial Base Class and Iterator Interface // NOTE: by substituting usual Arithmetic ops with big-integer ops, // big-integers can be handled transparently throughout all the combinatorial algorithms CombinatorialIterator = Abacus.CombinatorialIterator = Class({ - constructor: function CombinatorialIterator( n ) { - var self = this, klass; - if ( !(self instanceof CombinatorialIterator) ) return new CombinatorialIterator(n); - klass = self[CLASS]; + constructor: function CombinatorialIterator( n, order ) { + var self = this, klass = self[CLASS]; self.n = n || 0; self._count = klass.count( self.n ); - self.order( LEX ); // default order is lexicographic ("lex") + self.order( order ? order : LEX ); // default order is lexicographic ("lex") } ,__static__: { - count: NotImplemented( ) - ,rank: NotImplemented( ) - ,unrank: NotImplemented( ) - ,first: NotImplemented( ) - ,last: NotImplemented( ) - ,stochastic: NotImplemented( ) - ,dual: function( item, n, order ) { - return null == item ? null : ((LEX|REVLEX)&order ? item.slice( ) : reverse( complement( item, n ) )); - } - ,succ: function( offset, item, n, total, order ) { - var klass = this, Arithmetic = Abacus.Arithmetic; - if ( (-1 !== offset) && (1 !== offset) ) offset = 1; - return null == item ? null : klass.unrank( Arithmetic.add(klass.rank( item, n, total ), offset), n, total ); + Iterable: function CombinatorialIterable( iter ) { + if ( !(this instanceof CombinatorialIterable) ) return new CombinatorialIterable( iter ); + this.next = function( ) { + return iter.hasNext( ) ? {value: iter.next( )/*, key: iter.index( )*/} : {done: true}; + }; + } + + // some C-P-T processes at play here :)) + ,C: function( item, n ) { + return conjugation( item, n ); + } + ,P: function( item, n ) { + return parity( item ); + } + ,T: function( item, n ) { + return inversion( item, n ); + } + ,G: function( item, n ) { + return gray_encode( item, n ); } + + ,count: NotImplemented ,rand: function( n, total ) { var klass = this, Arithmetic = Abacus.Arithmetic, - tot = total ? total : klass.count( n ), - tot_1 = Arithmetic.sub(tot,1), r = Arithmetic.rnd(0, tot_1); - return Arithmetic.equ(0, r) - ? klass.first( n/*, LEX*/ ) - : (Arithmetic.equ(r, tot_1) - ? klass.last( n/*, LEX*/ ) - : klass.unrank( r, n, tot )); + tot = null != total ? total : klass.count( n ); + return klass.unrank( Arithmetic.rnd(Arithmetic.O, Arithmetic.sub(tot,1)), n, tot ); } + ,stochastic: NotImplemented + ,rank: NotImplemented + ,unrank: NotImplemented } ,n: 0 ,_order: 0 ,_count: 0 + ,__index: null ,_index: null ,__item: null ,_item: null @@ -713,6 +1005,7 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ self.n = null; self._order = null; self._count = 0; + self.__index = null; self._index = null; self.__item = null; self._item = null; @@ -731,11 +1024,13 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ var self = this; return [ self._order + ,self.__index ,self._index ,self.__item ,self._item ,self._prev ,self._next + ,self.n ]; } @@ -744,11 +1039,13 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ if ( state ) { self._order = state[0]; - self._index = state[1]; - self.__item = state[2]; - self._item = state[3]; - self._prev = state[4]; - self._next = state[5]; + self.__index = state[1]; + self._index = state[2]; + self.__item = state[3]; + self._item = state[4]; + self._prev = state[5]; + self._next = state[6]; + self.n = state[7]; } return self; } @@ -757,40 +1054,44 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ return this._count; } - ,order: function( order, reverse, T, doubly_stochastic ) { - var self = this, klass = self[CLASS], r, tot, n; + ,order: function( order, reverse, TM, doubly_stochastic ) { + var self = this, Arithmetic = Abacus.Arithmetic, O = Arithmetic.O, + klass = self[CLASS], T = klass.T, r, tot, tot_1, n, dir; if ( !arguments.length ) return self._order; if ( ('object' === typeof reverse) && (arguments.length < 4) ) { - doubly_stochastic = T; - T = reverse; + doubly_stochastic = TM; + TM = reverse; reverse = false; } else { reverse = false === reverse; } + order = ORDER( order ); - self._order = order; self._index = 0; + tot = self._count; n = self.n; + tot_1 = Arithmetic.sub(tot, 1); + dir = REVERSED & order ? T(1) : 1; + dir = reverse ? T(dir) : dir; + self._order = order; + self.__index = self._index = O; self._item = self.__item = null; self._prev = false; self._next = false; - tot = self._count; n = self.n; if ( STOCHASTIC & order ) { // lazy init - if ( (null != self._stochastic) && !T ) + if ( (null != self._stochastic) && !TM ) { if ( null != self._stochastic[2] ) self._stochastic[2] = []; // reset self.__item = klass.stochastic( self._stochastic[0], n, self._stochastic[2] ); - self._item = self.__item.slice( ); } - else if ( T ) + else if ( TM ) { - self._stochastic = [T, doubly_stochastic ? 1 : 0, doubly_stochastic ? [] : null]; + self._stochastic = [TM, doubly_stochastic ? 1 : 0, doubly_stochastic ? [] : null]; self.__item = klass.stochastic( self._stochastic[0], n, self._stochastic[2] ); - self._item = self.__item.slice( ); } else { @@ -799,194 +1100,212 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ } else if ( RANDOM & order ) { - // lazy init - if ( !self._traversed ) self._traversed = new Abacus.BitArray( tot ); - else self._traversed.reset( ); - self._traversed.set( r=self.randomIndex( ) ); - self.__item = self.item( r, LEX ); - self._item = null == self.__item ? null : self.__item.slice( ); + if ( Arithmetic.gt(tot, 100000) ) + { + // too big to keep in memeory + if ( self._traversed ) + { + self._traversed.dispose( ); + self._traversed = null; + } + r = self.randomIndex( ); + } + else + { + // lazy init + if ( !self._traversed ) self._traversed = new Abacus.BitArray( tot ); + else self._traversed.reset( ); + self._traversed.set( r=self.randomIndex( ) ); + } + self.__item = klass.unrank( r, n, tot ); + if ( null != self.__item ) self.__index = r; } else if ( MINIMAL & order ) { - /* TODO */ - self._item = self.__item = null; - } - else if ( REVCOLEX & order ) - { - self.__item = reverse ? klass.last( n, REVCOLEX ) : klass.first( n, REVCOLEX ); - self._item = klass.dual( self.__item, n, REVCOLEX ); + self.__item = self.item0( T(dir), order ); + if ( null != self.__item ) self.__index = -1 === dir ? O : T(O, tot_1); } else if ( COLEX & order ) { - self.__item = reverse ? klass.first( n, COLEX ) : klass.last( n, COLEX ); - self._item = klass.dual( self.__item, n, COLEX ); - } - else if ( REVLEX & order ) - { - self.__item = reverse ? klass.first( n, REVLEX ) : klass.last( n, REVLEX ); - self._item = klass.dual( self.__item, n, REVLEX ); + self.__item = self.item0( T(dir), order ); + if ( null != self.__item ) self.__index = -1 === dir ? O : T(O, tot_1); } else /*if ( LEX & order )*/ { - self.__item = reverse ? klass.last( n, LEX ) : klass.first( n, LEX ); - self._item = klass.dual( self.__item, n, LEX ); + self.__item = self.item0( dir, order ); + if ( null != self.__item ) self.__index = -1 === dir ? T(O, tot_1) : O; } - self._prev = (RANDOMISED & order) || !reverse ? false : null != self._item; - self._next = reverse && !(RANDOMISED & order) ? false : null != self._item; + self._item = null == self.__item ? null : self.dual( self.__item, STOCHASTIC & order ? null : self.__index, order ); + self._index = reverse && !(RANDOMISED & order) ? T(O, tot_1) : O; + self._prev = (RANDOMISED & order) || !reverse ? false : null != self.__item; + self._next = reverse && !(RANDOMISED & order) ? false : null != self.__item; return self; } ,index: function( index ) { if ( !arguments.length ) return this._index; - var self = this, Arithmetic = Abacus.Arithmetic, klass = self[CLASS], - n = self.n, tot = self._count, order = self._order, tot_1; + var self = this, Arithmetic = Abacus.Arithmetic, O = Arithmetic.O, + klass = self[CLASS], T = klass.T, + n = self.n, tot = self._count, order = self._order, tot_1, dir = REVERSED & order ? T(1) : 1; + + index = Arithmetic.wrapR(Arithmetic.N( index ), tot); - index = Arithmetic.num( index ); - if ( Arithmetic.gt(0, index) ) index = Arithmetic.add(index, tot); - if ( Arithmetic.gte(index, 0) && Arithmetic.lt(index, tot) ) + if ( !Arithmetic.equ(index, self._index) && Arithmetic.inside(index, -1, tot) ) { tot_1 = Arithmetic.sub(tot, 1); if ( MINIMAL & order ) { - /* TODO */ + self.__index = -1 === dir ? index : T(index, tot_1); self._index = index; - self._item = self.__item = null; - } - else if ( REVCOLEX & order ) - { - self._index = index; - self.__item = Arithmetic.equ(0, index) - ? klass.first( n, REVCOLEX ) + self.__item = Arithmetic.equ(O, index) + ? self.item0( T(dir), order ) : (Arithmetic.equ(tot_1, index) - ? klass.last( n, REVCOLEX ) - : klass.unrank( index, n, tot )); - self._item = klass.dual( self.__item, n, REVCOLEX ); + ? self.item0( dir, order ) + : klass.unrank( self.__index, n, tot )); + self._item = self.dual( self.__item, self.__index, order ); + self._prev = null != self.__item; + self._next = null != self.__item; } else if ( COLEX & order ) { + self.__index = -1 === dir ? index : T(index, tot_1); self._index = index; - self.__item = Arithmetic.equ(0, index) - ? klass.last( n, COLEX ) - : (Arithmetic.equ(tot_1, index) - ? klass.first( n, COLEX ) - : klass.unrank( Arithmetic.sub(tot_1,index), n, tot )); - self._item = klass.dual( self.__item, n, COLEX ); - } - else if ( REVLEX & order ) - { - self._index = index; - self.__item = Arithmetic.equ(0, index) - ? klass.last( n, REVLEX ) + self.__item = Arithmetic.equ(O, index) + ? self.item0( T(dir), order ) : (Arithmetic.equ(tot_1, index) - ? klass.first( n, REVLEX ) - : klass.unrank( Arithmetic.sub(tot_1,index), n, tot )); - self._item = klass.dual( self.__item, n, REVLEX ); + ? self.item0( dir, order ) + : klass.unrank( self.__index, n, tot )); + self._item = self.dual( self.__item, self.__index, order ); + self._prev = null != self.__item; + self._next = null != self.__item; } - else if ( LEX & order ) + else if ( !(RANDOMISED & order) ) { + self.__index = -1 === dir ? T(index, tot_1) : index; self._index = index; - self.__item = Arithmetic.equ(0, index) - ? klass.first( n, LEX ) + self.__item = Arithmetic.equ(O, index) + ? self.item0( dir, order ) : (Arithmetic.equ(tot_1, index) - ? klass.last( n, LEX ) - : klass.unrank( index, n, tot )); - self._item = klass.dual( self.__item, n, LEX ); + ? self.item0( T(dir), order ) + : klass.unrank( self.__index, n, tot )); + self._item = self.dual( self.__item, self.__index, order ); + self._prev = null != self.__item; + self._next = null != self.__item; } } return self; } - ,randomIndex: function( m, M ) { - var self = this, Arithmetic = Abacus.Arithmetic, tot = self._count, argslen = arguments.length; - if ( 0 === argslen ) - { - m = 0; - M = Arithmetic.sub(tot,1); - } - else if ( 1 === argslen ) - { - m = Arithmetic.num( m || 0 ); - M = Arithmetic.sub(tot,1); - } - else - { - m = Arithmetic.num( m ); - M = Arithmetic.num( M ); - } - return Arithmetic.rnd( m, M ); - } - ,item: function( index, order ) { if ( !arguments.length ) return this._item; - var self = this, n = self.n, tot = self._count, tot_1, - klass = self[CLASS], Arithmetic = Abacus.Arithmetic, traversed, r, rs; + var self = this, n = self.n, tot = self._count, tot_1, dir, indx, + klass = self[CLASS], T = klass.T, Arithmetic = Abacus.Arithmetic, O = Arithmetic.O; order = null != order ? ORDER( order ) : self._order; - index = Arithmetic.num( index ); - if ( Arithmetic.gt(0, index) ) index = Arithmetic.add(index, tot); - if ( Arithmetic.gte(index, 0) && Arithmetic.lt(index, tot) ) + index = Arithmetic.wrapR(Arithmetic.N( index ), tot); + + if ( (order === self._order) && Arithmetic.equ(index, self._index) ) return self._item; + + if ( Arithmetic.inside(index, -1, tot) ) { + dir = REVERSED & order ? -1 : 1; tot_1 = Arithmetic.sub(tot, 1); if ( RANDOM & order ) { - traversed = self._traversed; - // get next un-traversed index, reject if needed - r = self.randomIndex( ); rs = Abacus.Util.rnd( ) > 0.5 ? -1 : 1; - while ( traversed.isset( r ) ) - { - r = Arithmetic.add(r, rs); - if ( Arithmetic.lt(r, 0) ) r = tot_1; - else if ( Arithmetic.gte(r, tot) ) r = 0; - } - traversed.set( r ); - return klass.unrank( r, n, tot ); + indx = self.randomIndex( ); + return self.dual( + klass.unrank( indx, n, tot ) + /*klass.rand( n, tot )*/ + , indx, order + ); } else if ( MINIMAL & order ) { - /* TODO */ - return null; - } - else if ( REVCOLEX & order ) - { - return klass.dual( Arithmetic.equ(0, index) - ? klass.first( n, REVCOLEX ) + indx = -1 === dir ? index : T(index, tot_1); + return self.dual( Arithmetic.equ(O, index) + ? self.item0( T(dir), order ) : (Arithmetic.equ(tot_1, index) - ? klass.last( n, REVCOLEX ) - : klass.unrank( index, n, tot )), n, REVCOLEX ); + ? self.item0( dir, order ) + : klass.unrank( indx, n, tot )), indx, order ); } else if ( COLEX & order ) { - return klass.dual( Arithmetic.equ(0, index) - ? klass.last( n, COLEX ) + indx = -1 === dir ? index : T(index, tot_1); + return self.dual( Arithmetic.equ(O, index) + ? self.item0( T(dir), order ) : (Arithmetic.equ(tot_1, index) - ? klass.first( n, COLEX ) - : klass.unrank( Arithmetic.sub(tot_1,index), n, tot )), n, COLEX ); + ? self.item0( dir, order ) + : klass.unrank( indx, n, tot )), indx, order ); } - else if ( REVLEX & order ) - { - return klass.dual( Arithmetic.equ(0, index) - ? klass.last( n, REVLEX ) - : (Arithmetic.equ(tot_1, index) - ? klass.first( n, REVLEX ) - : klass.unrank( Arithmetic.sub(tot_1,index), n, tot )), n, REVLEX ); - } - else //if ( LEX & order ) + else /*if ( LEX & order )*/ { - return klass.dual( Arithmetic.equ(0, index) - ? klass.first( n, LEX ) + indx = -1 === dir ? T(index, tot_1) : index; + return self.dual( Arithmetic.equ(O, index) + ? self.item0( dir, order ) : (Arithmetic.equ(tot_1, index) - ? klass.last( n, LEX ) - : klass.unrank( index, n, tot )), n, LEX ); + ? self.item0( T(dir), order ) + : klass.unrank( indx, n, tot )), indx, order ); } } return null; } + ,dual: function( item, index, order ) { + if ( null == item ) return null; + order = order || 0; + var self = this, klass = self[CLASS], n = self.n, + // some C-P-T processes at play here + C = klass.C, P = klass.P, T = klass.T, G = klass.G, + reflected = REFLECTED & order; + + if ( RANDOMISED & order ) + return reflected + ? P( item, n ) + : item + ; + else if ( MINIMAL & order ) + return reflected + ? G( P( C( item, n ), n ), n ) + : P( G( P( C( item, n ), n ), n ), n ) + ; + else if ( COLEX & order ) + return reflected + ? C( item, n ) + : P( C( item, n ), n ) + ; + else /*if ( LEX & order )*/ + return reflected + ? P( item, n ) + : copy( item ) + ; + } + + ,randomIndex: function( m, M ) { + var self = this, Arithmetic = Abacus.Arithmetic, N = Arithmetic.N, O = Arithmetic.O, + tot = self._count, argslen = arguments.length; + if ( 0 === argslen ) + { + m = O; + M = Arithmetic.sub(tot,1); + } + else if ( 1 === argslen ) + { + m = N( m || 0 ); + M = Arithmetic.sub(tot,1); + } + else + { + m = N( m ); + M = N( M ); + } + return Arithmetic.rnd( m, M ); + } + ,random: function( ) { var self = this, klass = self[CLASS]; - return klass.rand( self.n, self._count ); + return self.dual( klass.rand( self.n, self._count ), null, RANDOM|self._order ); } ,rewind: function( ) { @@ -1005,136 +1324,142 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ return RANDOMISED & this._order ? false : this._prev; } + // some C-P-T processes at play here as well, see below + ,item0: NotImplemented + + // some C-P-T processes at play and here as well, see below + ,succ: function( dir, item, index, order ) { + var self = this, klass = self[CLASS], + Arithmetic = Abacus.Arithmetic, + total = self._count, n = self.n; + return null == item + ? null + : klass.unrank(Arithmetic.add(/*klass.rank(item, n, total)*/index, -1===dir?-1:1), n, total) + ; + } + + // some C-P-T processes at play here as well, see below ,next: function( ) { - var self = this, Arithmetic = Abacus.Arithmetic, order = self._order, traversed, r, - klass = self[CLASS], current = self._item, n = self.n, tot = self._count, tot_1, rs; + var self = this, Arithmetic = Abacus.Arithmetic, O = Arithmetic.O, + order = self._order, traversed, r, dir, + klass = self[CLASS], T = klass.T, current = self._item, n = self.n, tot = self._count, tot_1, rs; if ( STOCHASTIC & order ) { self.__item = klass.stochastic( self._stochastic[0], n, self._stochastic[2] ); - self._item = self.__item.slice( ); } else if ( RANDOM & order ) { - tot_1 = Arithmetic.sub(tot, 1); - if ( Arithmetic.lt(self._index, tot_1) ) + traversed = self._traversed; + if ( !traversed ) { - traversed = self._traversed; - // get next un-traversed index, reject if needed - r = self.randomIndex( ); rs = Abacus.Util.rnd( ) > 0.5 ? -1 : 1; - while ( traversed.isset( r ) ) - { - r = Arithmetic.add(r, rs); - if ( Arithmetic.lt(r, 0) ) r = tot_1; - else if ( Arithmetic.gt(r, tot_1) ) r = 0; - } - traversed.set( r ); - self.__item = self.item( r, LEX ); - self._item = null == self.__item ? null : self.__item.slice( ); + r = self.randomIndex( ); + self.__item = klass.unrank( r, n, tot ); + if ( null != self.__item ) self.__index = r; } else { - self._item = self.__item = null; - if ( self._traversed ) + tot_1 = Arithmetic.sub(tot, 1); + if ( Arithmetic.lt(self._index, tot_1) ) { - self._traversed.dispose( ); - self._traversed = null; + // get next un-traversed index, reject if needed + r = self.randomIndex( ); + rs = Abacus.Math.rnd( ) > 0.5 ? -1 : 1; + while ( traversed.isset( r ) ) r = Arithmetic.wrap( Arithmetic.add(r, rs), O, tot_1 ); + traversed.set( r ); + self.__item = klass.unrank( r, n, tot ); + if ( null != self.__item ) self.__index = r; + } + else + { + self._item = self.__item = null; + if ( self._traversed ) + { + self._traversed.dispose( ); + self._traversed = null; + } } } } else { + dir = REVERSED & order ? T(1) : 1; // compute next, using successor methods / loopless algorithms, WITHOUT using big integer arithemtic if ( MINIMAL & order ) { - /* TODO */ - self._item = self.__item = null; - } - else if ( REVCOLEX & order ) - { - self.__item = klass.succ( 1, self.__item, n, tot, REVCOLEX ); - self._item = klass.dual( self.__item, n, REVCOLEX ); + self.__item = self.succ( T(dir), self.__item, self.__index, order ); + if ( null != self.__item ) self.__index = Arithmetic.add(self.__index, T(dir)); } else if ( COLEX & order ) { - self.__item = klass.succ( -1, self.__item, n, tot, COLEX ); - self._item = klass.dual( self.__item, n, COLEX ); - } - else if ( REVLEX & order ) - { - self.__item = klass.succ( -1, self.__item, n, tot, REVLEX ); - self._item = klass.dual( self.__item, n, REVLEX ); + self.__item = self.succ( T(dir), self.__item, self.__index, order ); + if ( null != self.__item ) self.__index = Arithmetic.add(self.__index, T(dir)); } else /*if ( LEX & order )*/ { - self.__item = klass.succ( 1, self.__item, n, tot, LEX ); - self._item = klass.dual( self.__item, n, LEX ); + self.__item = self.succ( dir, self.__item, self.__index, order ); + if ( null != self.__item ) self.__index = Arithmetic.add(self.__index, dir); } } - self._next = null != self._item; + self._item = null == self.__item ? null : self.dual( self.__item, STOCHASTIC & order ? null : self.__index, order ); + self._next = null != self.__item; if ( self._next && !(STOCHASTIC & order) ) self._index = Arithmetic.add(self._index, 1); return current; } + // some C-P-T processes at play here as well, see below ,prev: function( ) { - var self = this, Arithmetic = Abacus.Arithmetic, order = self._order, - klass = self[CLASS], current = self._item, n = self.n, tot = self._count; + var self = this, Arithmetic = Abacus.Arithmetic, order = self._order, dir, + klass = self[CLASS], T = klass.T, current = self._item, n = self.n, tot = self._count; // random and stochastic order has no prev if ( RANDOMISED & order ) return null; + dir = REVERSED & order ? T(1) : 1; // compute prev, using successor methods / loopless algorithms, WITHOUT using big integer arithemtic if ( MINIMAL & order ) { - /* TODO */ - self._item = self.__item = null; - } - else if ( REVCOLEX & order ) - { - self.__item = klass.succ( -1, self.__item, n, tot, REVCOLEX ); - self._item = klass.dual( self.__item, n, REVCOLEX ); + self.__item = self.succ( dir, self.__item, self.__index, order ); + if ( null != self.__item ) self.__index = Arithmetic.add(self.__index, dir); } else if ( COLEX & order ) { - self.__item = klass.succ( 1, self.__item, n, tot, COLEX ); - self._item = klass.dual( self.__item, n, COLEX ); - } - else if ( REVLEX & order ) - { - self.__item = klass.succ( 1, self.__item, n, tot, REVLEX ); - self._item = klass.dual( self.__item, n, REVLEX ); + self.__item = self.succ( dir, self.__item, self.__index, order ); + if ( null != self.__item ) self.__index = Arithmetic.add(self.__index, dir); } else /*if ( LEX & order )*/ { - self.__item = klass.succ( -1, self.__item, n, tot, LEX ); - self._item = klass.dual( self.__item, n, LEX ); + self.__item = self.succ( T(dir), self.__item, self.__index, order ); + if ( null != self.__item ) self.__index = Arithmetic.add(self.__index, T(dir)); } - self._prev = null != self._item; - if ( self._prev && !(RANDOMISED & order) ) self._index = Arithmetic.sub(self._index, 1); + self._item = null == self.__item ? null : self.dual( self.__item, self.__index, order ); + self._prev = null != self.__item; + if ( self._prev ) self._index = Arithmetic.sub(self._index, 1); return current; } ,range: function( start, end ) { - var self = this, Arithmetic = Abacus.Arithmetic, + var self = this, Arithmetic = Abacus.Arithmetic, N = Arithmetic.N, O = Arithmetic.O, tmp, tot = self._count, range, count, i, iter_state, dir = 1, - argslen = arguments.length, tot_1 = Arithmetic.sub(tot,1); + argslen = arguments.length, tot_1 = Arithmetic.sub(tot,1), + not_randomised = !(RANDOMISED & self._order); if ( argslen < 1 ) { - start = 0; + start = O; end = tot_1; } else if ( argslen < 2 ) { - start = Arithmetic.num( start ); + start = N( start ); end = tot_1; } else { - start = Arithmetic.num( start ); - end = Arithmetic.num( end ); + start = N( start ); + end = N( end ); } - if ( Arithmetic.lt(start, 0) ) start = Arithmetic.add(start,tot); - if ( Arithmetic.lt(end, 0) ) end = Arithmetic.add(end,tot); + start = Arithmetic.wrapR( start, tot ); + end = Arithmetic.wrapR( end, tot ); if ( Arithmetic.gt(start, end) ) { tmp = start; @@ -1142,13 +1467,13 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ end = tmp; dir = -1; } - if ( Arithmetic.lt(start, 0) ) start = 0; - if ( Arithmetic.gt(end, tot_1) ) end = tot_1; + start = Arithmetic.clamp( start, O, tot_1 ); + if ( not_randomised ) end = Arithmetic.clamp( end, O, tot_1 ); if ( Arithmetic.lte(start, end) ) { // store current iterator state iter_state = self._store( ); - if ( !(RANDOMISED & self._order) ) self.index( start ); + if ( not_randomised ) self.index( start ); count = Arithmetic.val(Arithmetic.sub(end, start)); range = new Array( count+1 ); if ( 0 > dir ) for (i=count; i>=0; i--) range[ i ] = self.next( ); else for (i=0; i<=count; i++) range[ i ] = self.next( ); @@ -1161,170 +1486,66 @@ CombinatorialIterator = Abacus.CombinatorialIterator = Class({ } return range; } + + // javascript @@iterator/@@iterable interface, if supported + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols + ,__iter__: function( ) { + return new CombinatorialIterator.Iterable( this ); + } }); +if ( ('undefined' !== typeof Symbol) && ('undefined' !== typeof Symbol.iterator) ) +{ + // add javascript-specific iterator interface, if supported + CombinatorialIterator[PROTO][Symbol.iterator] = CombinatorialIterator[PROTO].__iter__; +} // https://en.wikipedia.org/wiki/Permutations Permutation = Abacus.Permutation = Class(CombinatorialIterator, { // extends and implements CombinatorialIterator - constructor: function Permutation( n ) { + constructor: function Permutation( n, multiset ) { var self = this; - if ( !(self instanceof Permutation) ) return new Permutation(n); - CombinatorialIterator.call(self, n); + if ( !(self instanceof Permutation) ) return new Permutation(n, multiset); + CombinatorialIterator.call(self, [n, '[object Array]' === toString.call(multiset) ? multiset : false]); } ,__static__: { - count: function( n ) { - return factorial( n ); - } - ,dual: CombinatorialIterator.dual - ,rank: function( perm, n ) { - // O(n log n) uniform lexicographic ranking. - var Arithmetic = Abacus.Arithmetic, - index = 0, i, j, node, ctr, - k = Arithmetic.ceil(log2(n)), Tl = (1<<(1+k))-1, - T = new Array(Tl), twok = Arithmetic.shl(1,k); - for(i=0; i>> 1) << 1]); - T[node] = Arithmetic.add(T[node],1); - node >>>= 1; - } - T[node] = Arithmetic.add(T[node],1); - index = Arithmetic.add(Arithmetic.mul(index, Arithmetic.sub((n, i))), ctr); - } - return index; + C: function( item, n ) { + return conjugation( item, n[0] ); } - ,unrank: function( index, n, total ) { - // O(n log n) uniform lexicographic unranking. - var Arithmetic = Abacus.Arithmetic, klass = this, - perm, fn, i, j, i2, - digit, node, rem, k, Tl, T, twok; - - total = total || factorial(n); - if ( Arithmetic.equ(0, index) ) return klass.first( n ); - else if ( Arithmetic.equ(total, Arithmetic.add(index,1)) ) return klass.last( n ); - - perm = new Array(n); fn = Arithmetic.div(total, n); - k = Arithmetic.ceil(log2(n)); Tl = (1<<(1+k))-1; - T = new Array(Tl); twok = Arithmetic.shl(1,k); - - for (i=0; i<=k; i++) - for (j=1,i2=1< a[k + 1]. - k = n-2; - while (k>=0 && next[k]<=next[k+1]) k--; - // If no such index exists, the permutation is the last permutation. - if ( k >=0 ) - { - //Find the largest index kl greater than k such that a[k] > a[kl]. - kl = n-1; - while (kl>k && next[k]<=next[kl]) kl--; - //Swap the value of a[k] with that of a[l]. - s = next[k]; next[k] = next[kl]; next[kl] = s; - //Reverse the sequence from a[k + 1] up to and including the final element a[n]. - l = k+1; r = n-1; - while (l < r) {s = next[l]; next[l++] = next[r]; next[r--] = s;} - } - else - { - next = null; - } - } - else //if ( 1 === offset ) - { - //Find the largest index k such that a[k] < a[k + 1]. - k = n-2; - while (k>=0 && next[k]>=next[k+1]) k--; - // If no such index exists, the permutation is the last permutation. - if ( k >=0 ) - { - //Find the largest index kl greater than k such that a[k] < a[kl]. - kl = n-1; - while (kl>k && next[k]>=next[kl]) kl--; - //Swap the value of a[k] with that of a[l]. - s = next[k]; next[k] = next[kl]; next[kl] = s; - //Reverse the sequence from a[k + 1] up to and including the final element a[n]. - l = k+1; r = n-1; - while (l < r) {s = next[l]; next[l++] = next[r]; next[r--] = s;} - } - else - { - next = null; - } - } - return next; + return Abacus.Math.Factorial( n[0] ); } - return null; } ,rand: function( n ) { - var perm = new Array(n), i; - for (i=0; i>> 1) << 1]); + T[node] = Arithmetic.add(T[node],1); + node >>>= 1; + } + T[node] = Arithmetic.add(T[node],1); + index = Arithmetic.add(Arithmetic.mul(index, N(n-i)), ctr); + } + return index; + } + ,unrank: function( index, n, total ) { + // O(n log n) uniform lexicographic unranking. + var Arithmetic = Abacus.Arithmetic, klass = this, + N = Arithmetic.N, O = Arithmetic.O, I = Arithmetic.I, + item, fn, i, j, i2, + digit, node, rem, k, Tl, T, twok; + + total = null != total ? total : klass.count( n ); + //if ( Arithmetic.equ(0, index) ) return klass.first( n, 1 ); + //else if ( Arithmetic.equ(total, Arithmetic.add(index,1)) ) return klass.first( n, -1 ); + + n = n[0]; + item = new Array(n); fn = Arithmetic.div(total, n); + k = Abacus.Math.ceil(log2(n)); Tl = (1<<(1+k))-1; + T = new Array(Tl); twok = Arithmetic.shl(I,k); + + for (i=0; i<=k; i++) + for (j=1,i2=1< a[k + 1]. + k = n-2; + while (k>=0 && item[k]<=item[k+1]) k--; + // If no such index exists, the permutation is the last permutation. + if ( k >=0 ) + { + //Find the largest index kl greater than k such that a[k] > a[kl]. + kl = n-1; + while (kl>k && item[k]<=item[kl]) kl--; + //Swap the value of a[k] with that of a[l]. + s = next[k]; next[k] = next[kl]; next[kl] = s; + //Reverse the sequence from a[k + 1] up to and including the final element a[n]. + l = k+1; r = n-1; + while (l < r) {s = next[l]; next[l++] = next[r]; next[r--] = s;} + } + else + { + next = null; + } + } + else //if ( 1 === offset ) { - if ( perm[i] > m ) m = perm[i]; // update max. - if ( m <= i ) return false; // prefix mapped to itself, P not connected. + //Find the largest index k such that a[k] < a[k + 1]. + k = n-2; + while (k>=0 && item[k]>=item[k+1]) k--; + // If no such index exists, the permutation is the last permutation. + if ( k >=0 ) + { + //Find the largest index kl greater than k such that a[k] < a[kl]. + kl = n-1; + while (kl>k && item[k]>=item[kl]) kl--; + //Swap the value of a[k] with that of a[l]. + s = next[k]; next[k] = next[kl]; next[kl] = s; + //Reverse the sequence from a[k + 1] up to and including the final element a[n]. + l = k+1; r = n-1; + while (l < r) {s = next[l]; next[l++] = next[r]; next[r--] = s;} + } + else + { + next = null; + } } - return true; // P is connected. + return next; } + return null; } }); @@ -1530,161 +1867,153 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, { Combination = Abacus.Combination = Class(CombinatorialIterator, { // extends and implements CombinatorialIterator - constructor: function Combination( n, k ) { + constructor: function Combination( n, k, type ) { var self = this; - if ( !(self instanceof Combination) ) return new Combination(n, k); - CombinatorialIterator.call(self, [n, k]); + if ( !(self instanceof Combination) ) return new Combination(n, k, type); + CombinatorialIterator.call(self, [n, k, "repeated"===String(type).toLowerCase()]); } ,__static__: { - count: function( n ) { - return binomial( n[0], n[1] ); + C: function( item, n ) { + return conjugation( item, n[0] ); + } + ,P: CombinatorialIterator.P + ,T: CombinatorialIterator.T + ,G: function( item, n ) { + return gray_encode( item, n[0] ); + } + + ,count: function( n ) { + return Abacus.Math.Binomial( n[2] ? n[0]+n[1]-1 : n[0], n[1] ); } - ,dual: function( item, n, order ) { - return CombinatorialIterator.dual.call( this, item, n[0], order ); + ,rand: function( n ) { + var item, i, k, n_k, c, rndInt = Abacus.Math.rndInt, repeated = n[2]; + k = n[1]; n = n[0]; n_k = n-k; c = n-1; + if ( repeated ) + { + if ( 1 === k ) + { + item = [rndInt(0, c)]; + } + else + { + // O(klogk) worst-case, unbiased + item = []; + for(i=0; i 0 ); - } + m--; p--; + } + else + { + binom = Arithmetic.div(Arithmetic.mul(binom,NN(p-m)),p); + t--; p--; + } + } while( m > 0 ); + /*}*/ return item; } - ,first: function( n ) { - var i, k = n[1], comb = new Array(k); - for (i=0; i 0 ) - { - if ( next[i]>next[i-1]+1 ) { index = i; break; } - i--; - } - if (-1 === index && 0 < next[0]) index = 0; - // adjust next indexes after the moved index - if ( -1 < index ) - { - curr = n; - for (i=k-1; i>index; i--) next[i] = --curr; - next[index]--; - } - else - { - next = null; - } - } - else //if ( 1 === offset ) - { - // compute next indexes - // find index to move - i = k-1; index = -1; limit = n-k; - while ( 0 <= i ) - { - if ( next[i] < limit+i ) { index = i; break; } - i--; - } - // adjust next indexes after the moved index - if ( -1 < index ) - { - curr = next[index]; - for (i=index; inext[i-1]+ofs ) { index = i; break; } + i--; + } + if (-1 === index && 0 < next[0]) index = 0; + // adjust next indexes after the moved index + if ( -1 < index ) + { + curr = n-1+ofs; + for (i=k-1; i>index; i--) { - index = Arithmetic.sub(index,binom); - binom = Arithmetic.div(Arithmetic.mul(binom,m),p); + curr -= ofs; + next[i] = curr; } - m--; p--; + next[index]--; } - else - { - binom = Arithmetic.div(Arithmetic.mul(binom,Arithmetic.sub(p,m)),p); - //binom = Arithmetic.div(Arithmetic.sub(p,m),p); - t--; p--; + else + { + next = null; } - } while( m > 0 ); - return item; - } - ,first: function( n ) { - var i, k = n[1], comb = new Array(k); - for (i=0; i next[i-1] ) { index=i; break; } + if ( next[i] < n-1 ) { index = i; break; } i--; } - if (-1 === index && 0 < next[0]) index = 0; - // adjust next indexes after the moved index - if (-1 < index) - { - curr = n-1; - for (i=index+1; i 1 ? 2 : 1, k, m; + C: function( item, n ) { + return conjugate_partition( item ); + } + ,P: CombinatorialIterator.P + ,T: CombinatorialIterator.T + ,G: function( item, n ) { + return gray_encode( item, n[0] ); + } + + ,count: function( n ) { + n = n[0]; + var partitions = Abacus.Math.Partitions, add = Abacus.Arithmetic.add, + p = Abacus.Arithmetic.N(n > 1 ? 2 : 1), k, m; for (k=2; k=1; m--) p = add(p,partitions(n, k, m)); return p; } - ,dual: function( item, n ) { - if ( null == item ) return null; - var compl = [], i, l = item.length, k; - for (i=0; i= k ) continue; - if ( n === k ) return [n]; - compl.unshift(k); - } - return compl; + ,rand: function( n, total ) { + return null; } - ,rank: function( item, n, total, s, e ) { + ,stochastic: CombinatorialIterator.stochastic + ,rank: function( item, n, total, order, s, e ) { + return Abacus.Arithmetic.O; + /*n = n[0]; var Arithmetic = Abacus.Arithmetic, klass = this, index, i, l = item.length, k, nk = n; - total = total || klass.count( n ); + total = null != total ? total : klass.count( n ); s = s || 0; e = e || l; i = s; k = item[i]; if ( nk === k ) index = Arithmetic.sub(total,1); else if ( 1 === k ) index = 0; - else if ( i+1 < l ) index = Arithmetic.add(1, klass.rank(item, n-k, Arithmetic.sub(total,klass.count( n-k )), i+1)); + else if ( i+1 < l ) index = Arithmetic.add(1, klass.rank(item, [n-k], Arithmetic.sub(total,klass.count( n-k )), order, i+1)); else index = 0; - return index; + return index;*/ } ,unrank: function( index, n, total ) { /*var klass = this, item = [], i, k, nk = n; @@ -1934,110 +2307,24 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, { return item;*/ return null; } - ,first: function( n ) { - var i, item = new Array(n); - for (i=0; i 1 ) - { - c = next.length; - // break into a partition with last part reduced by 1 from previous partition series - i = c-1; - while (i>=0 && 1 === next[i]) i--; - p1 = next[i]-1; - next = next.slice(0, i+1); - next[ i ] = p1; - summa = sum( next ); - rem = n-summa; - while ( rem > 0 ) - { - p2 = rem; - if ( p2 > p1 ) - { - p2 = p1; - next.push(p2); - } - else - { - next.push(rem); - } - rem -= p2; - } - } - // if partition is all ones (so first element is also one) it is the final partition - else - { - next = null; - } - } - else //if ( 1 === offset ) - { - // compute next partition - if ( next[0] < n ) - { - c = next.length; - i = c-1; if (i>0) i--; - while (i>0 && next[i] === next[i-1]) i--; - next[i]++; - next = next.slice( 0, i+1 ); - summa = sum( next ); - rem = n-summa; - while ( rem > 0 ) - { - next.push(1); - rem--; - } - } - // if partition is the number itself it is the final partition - else - { - next = null; - } - } - return next; - } - return null; - } - ,rand: function( n, total ) { - return null; - } - ,stochastic: CombinatorialIterator.stochastic ,conjugate: function( partition ) { - // http://mathworld.wolfram.com/ConjugatePartition.html - var l = partition.length, - n = partition[0], i, j, p, - conjugate = new Array(n); - for (i=0; i 0 ) - { - conjugate[i++]++; - p--; - } - } - return conjugate; + return conjugate_partition( partition ); } ,pack: function( partition ) { var packed = [], i, l = partition.length, last = partition[0], part = [last, 1]; for (i=1; i 1 ) + { + c = next.length; + // break into a partition with last part reduced by 1 from previous partition series + i = c-1; + while (i>=0 && 1 === next[i]) i--; + p1 = next[i]-1; + next = next.slice(0, i+1); + next[ i ] = p1; + summa = sum( next ); + rem = n-summa; + while ( rem > 0 ) + { + p2 = rem; + if ( p2 > p1 ) + { + p2 = p1; + next.push(p2); + } + else + { + next.push(rem); + } + rem -= p2; + } + } + // if partition is all ones (so first element is also one) it is the final partition + else + { + next = null; + } + // invC of item } - return subset; - } - ,rand: function( n, total ) { - var item = CombinatorialIterator.rand.call(this, n, total); - return null == item ? null : item.reverse( ); - } - ,stochastic: CombinatorialIterator.stochastic - // LEX / COLEX ordering implementation is somewhat reversed here in order to produce correct output - ,dual: function( item, n, order ) { - return null == item ? null : ((COLEX|REVCOLEX|RANDOMISED)&order ? item.slice( ) : reverse(complement(item, n, true))); - } - ,first: function( n, order ) { - /*if ( (COLEX|REVCOLEX) & (order||0) ) return this.last( n, LEX ); - return [];*/ - var i, item = new Array( n ); - for (i=0; i0) i--; + while (i>0 && next[i] === next[i-1]) i--; + next[i]++; + next = next.slice( 0, i+1 ); + summa = sum( next ); + rem = n-summa; + while ( rem > 0 ) + { + next.push(1); + rem--; + } + } + // if partition is the number itself it is the final partition + else + { + next = null; + } + } + return next; } + return null; } }); +// aliases +Partition.transpose = Partition.conjugate; // // https://en.wikipedia.org/wiki/Outer_product @@ -2144,13 +2447,13 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, { // extends and implements CombinatorialIterator constructor: function Tensor( /*dims here ..*/ ) { - var self = this; + var self = this, args = arguments; if ( !(self instanceof Tensor) ) { self = new Tensor( ); - if ( arguments.length ) + if ( args.length ) { - CombinatorialIterator.call(self, slice.call(arguments)); + CombinatorialIterator.call(self, args[0] instanceof Array ? args[0] : slice.call(args)); } else { @@ -2159,9 +2462,9 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, { } return self; } - if ( arguments.length ) + if ( args.length ) { - CombinatorialIterator.call(self, slice.call(arguments)); + CombinatorialIterator.call(self, args[0] instanceof Array ? args[0] : slice.call(args)); } else { @@ -2171,88 +2474,40 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, { } ,__static__: { - count: function( n ) { - return !n || !n.length ? 0 : prod( n ); + C: CombinatorialIterator.C + ,P: CombinatorialIterator.P + ,T: CombinatorialIterator.T + ,G: CombinatorialIterator.G + + ,count: function( n ) { + return !n || !n.length ? 0 : product( n ); } - ,dual: function( item, n, order ) { - if ( (LEX|REVLEX) & order ) return null == item ? null : item.slice( ); - return null == item ? null : complement( item, n, false, true ); + ,rand: function( n ) { + var rndInt = Abacus.Math.rndInt, i, d = n, nd = d.length, item = new Array(nd); + for (i=0; i=0; i--) { l = d[ i ]; t = Arithmetic.mod(r, l); r = Arithmetic.div(r, l); - tensor[ i ] = Arithmetic.val(t); + item[ i ] = Arithmetic.val(t); } - return tensor; - } - ,first: function( n ) { - var i, nd = n.length, tensor = new Array( nd ); - for (i=0; i=0 && next[i]-1 < 0 ) i--; - if ( 0 <= i ) - { - next[i]--; - for (j=i+1; j=0 && next[i]+1 === d[i] ) i--; - if ( 0 <= i ) - { - next[i]++; - for (j=i+1; j=0 && next[i]-1 < 0 ) i--; + if ( 0 <= i ) + { + next[i]--; + for (j=i+1; j=0 && next[i]+1 === d[i] ) i--; + if ( 0 <= i ) + { + next[i]++; + for (j=i+1; j=0; i--) { l = n; t = Arithmetic.mod(r, l); r = Arithmetic.div(r, l); - tuple[ i ] = Arithmetic.val(t); + item[ i ] = Arithmetic.val(t); } - return tuple; - } - ,first: function( n ) { - var i, k = n[0], tuple = new Array( k ); - for (i=0; i=0 && next[i]-1 < 0 ) i--; + if ( 0 <= i ) { - i = k-1; - while ( i >=0 && next[i]-1 < 0 ) i--; - if ( 0 <= i ) - { - next[i]--; - for (j=i+1; j=0 && next[i]+1 === n ) i--; - if ( 0 <= i ) - { - next[i]++; - for (j=i+1; j=0 && next[i]+1 === n ) i--; + if ( 0 <= i ) + { + next[i]++; + for (j=i+1; j0&&(e=new Array(n+1).join("0")+e),e}},p=A(32),w=function(t,r,n,e){if(n>e)return r;var i,u,o=e-n+1,l=15&o,a=1&l,f=a?t(r,n):r;for(i=a;l>i;i+=2)u=n+i,f=t(t(f,u),u+1);for(i=l;o>i;i+=16)u=n+i,f=t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(f,u),u+1),u+2),u+3),u+4),u+5),u+6),u+7),u+8),u+9),u+10),u+11),u+12),u+13),u+14),u+15);return f},b=function(t,r,n,e,i,u){var o=t.length;if(arguments.length<5&&(i=o-1),0>i&&(i+=o),arguments.length<4&&(e=0),e>i)return n;if(!0===u){var l,a,f=i-e+1,c=f-1,s=15&f,_=1&s,h=c-s,d=_?r(n,t[i],i):n;for(l=c-_;l>h;l-=2)a=e+l,d=r(r(d,t[a],a),t[a-1],a-1);for(l=h;l>=0;l-=16)a=e+l,d=r(r(r(r(r(r(r(r(r(r(r(r(r(r(r(r(d,t[a],a),t[a-1],a-1),t[a-2],a-2),t[a-3],a-3),t[a-4],a-4),t[a-5],a-5),t[a-6],a-6),t[a-7],a-7),t[a-8],a-8),t[a-9],a-9),t[a-10],a-10),t[a-11],a-11),t[a-12],a-12),t[a-13],a-13),t[a-14],a-14),t[a-15],a-15)}else{var l,a,f=i-e+1,s=15&f,_=1&s,d=_?r(n,t[e],e):n;for(l=_;s>l;l+=2)a=e+l,d=r(r(d,t[a],a),t[a+1],a+1);for(l=s;f>l;l+=16)a=e+l,d=r(r(r(r(r(r(r(r(r(r(r(r(r(r(r(r(d,t[a],a),t[a+1],a+1),t[a+2],a+2),t[a+3],a+3),t[a+4],a+4),t[a+5],a+5),t[a+6],a+6),t[a+7],a+7),t[a+8],a+8),t[a+9],a+9),t[a+10],a+10),t[a+11],a+11),t[a+12],a+12),t[a+13],a+13),t[a+14],a+14),t[a+15],a+15)}return d},y=function(t,r,n,e,i){var u=t.length;if(arguments.length<4&&(e=u-1),0>e&&(e+=u),arguments.length<3&&(n=0),n>e)return[];var o,l,a,f,c,s,_=e-n+1,h=new Array(_);if(!0===i){for(a=_-1,c=15&_,s=1&c,f=a-c,s&&(h[0]=r(t[e],e,n,e)),o=a-s;o>f;o-=2)l=n+o,h[o]=r(t[l],l,n,e),h[o+1]=r(t[l-1],l-1,n,e);for(o=f;o>=0;o-=16)l=n+o,h[o]=r(t[l],l,n,e),h[o+1]=r(t[l-1],l-1,n,e),h[o+2]=r(t[l-2],l-2,n,e),h[o+3]=r(t[l-3],l-3,n,e),h[o+4]=r(t[l-4],l-4,n,e),h[o+5]=r(t[l-5],l-5,n,e),h[o+6]=r(t[l-6],l-6,n,e),h[o+7]=r(t[l-7],l-7,n,e),h[o+8]=r(t[l-8],l-8,n,e),h[o+9]=r(t[l-9],l-9,n,e),h[o+10]=r(t[l-10],l-10,n,e),h[o+11]=r(t[l-11],l-11,n,e),h[o+12]=r(t[l-12],l-12,n,e),h[o+13]=r(t[l-13],l-13,n,e),h[o+14]=r(t[l-14],l-14,n,e),h[o+15]=r(t[l-15],l-15,n,e)}else{for(c=15&_,s=1&c,s&&(h[0]=r(t[n],n,n,e)),o=s;c>o;o+=2)l=n+o,h[o]=r(t[l],l,n,e),h[o+1]=r(t[l+1],l+1,n,e);for(o=c;_>o;o+=16)l=n+o,h[o]=r(t[l],l,n,e),h[o+1]=r(t[l+1],l+1,n,e),h[o+2]=r(t[l+2],l+2,n,e),h[o+3]=r(t[l+3],l+3,n,e),h[o+4]=r(t[l+4],l+4,n,e),h[o+5]=r(t[l+5],l+5,n,e),h[o+6]=r(t[l+6],l+6,n,e),h[o+7]=r(t[l+7],l+7,n,e),h[o+8]=r(t[l+8],l+8,n,e),h[o+9]=r(t[l+9],l+9,n,e),h[o+10]=r(t[l+10],l+10,n,e),h[o+11]=r(t[l+11],l+11,n,e),h[o+12]=r(t[l+12],l+12,n,e),h[o+13]=r(t[l+13],l+13,n,e),h[o+14]=r(t[l+14],l+14,n,e),h[o+15]=r(t[l+15],l+15,n,e)}return h},x=function(t,r){for(var n=0,e=0,i=[],u=t.length,o=r.length;u>n&&o>e;)t[n]r[e]?e++:(i.push(t[n]),n++,e++);return i},k=function(t,r,n){var e,i,u=0,o=0,l=[],a=t.length,f=r.length;for(n=!1!==n,i=!n;a>u&&f>o;){if(n&&l.length){if(t[u]===e){u++;continue}if(r[o]===e){o++;continue}}t[u]r[o]?l.push(e=r[o++]):(l.push(e=t[u]),i&&l.push(r[o]),u++,o++)}for(;a>u;)(i||t[u]!==e)&&l.push(e=t[u++]);for(;f>o;)(i||r[o]!==e)&&l.push(e=r[o++]);return l},U=function(){var t,r,n,e,i,u,o,l,a,f,c=arguments,s=c.length;if(!s)return[];for(a=c[0].length,t=1;s>t;t++)a*=c[t].length;for(f=new Array(a),t=0;a>t;t++){for(l=[],n=t,r=s-1;r>=0;r--)if(e=c[r].length,i=n%e,n=~~(n/e),o=c[r][i],o instanceof Array)for(u=o.length-1;u>=0;u--)l.unshift(o[u]);else l.unshift(o);f[t]=l}return f},C=function(){var t,r,n,e,i,u,o,l=arguments,a=l.length;if(!a)return[];for(u=l[0].length,t=1;a>t;t++)ut;t++){for(n=[],r=a-1;r>=0;r--)if(e=l[r].length=0;i--)n.unshift(e[i]);else n.unshift(e);o[t]=n}return o},q=function(t,r,n){var e,i,u,o,l,a=f.Util.rint;for(o=!0===n?t.slice():t,l=!0===r?1:0,e=o.length;lu;u++)o=a(0,--c),l=t[o],t[o]=t[c],t[c]=l,e[u]=l,n&&(i[u]=o);if(n)for(u=r-1;u>=0;u--)o=i[u],l=t[c],t[c]=t[o],t[o]=l,c++;return e},I=function(t,r,n,e){if(null==t)return null;if(!0===n){var i,u,o,l,a=t.length,f=r-a;if(0>=r||0>=f)return[];for(i=new Array(f),u=0,o=0,l=0;f>l;)o>=a||uc;c++)i[c]=r[c]-1-t[c];else for(c=0;a>c;c++)i[c]=r-1-t[c];return i},O=function(t){return null==t?null:t.reverse()},R=function(t){var r,n=[],e=t.length;if(e>1)for(r=e-1;r>=1;r--)n.push([t[0],t[r]]);return n},M=function(t){var r=f.Arithmetic.add;return b(t,r,0)},L=function(t){var r=f.Arithmetic.mul;return b(t,r,1)},S=function(t){return f.Arithmetic.shl(1,t)},N=function(t,r){return f.Arithmetic.pow(t,r)},P=function(t){var r=f.Arithmetic.mul;return 0>t?0:2>t?1:4>t?t<t-r&&(r=t-r),0>r||1>t)return 0;if(0===r||1===t)return 1;if(1===r)return t;var n,e=f.Arithmetic.mul,i=t-r,u=1+i;for(n=2;r>=n;n++)u=e(u,1+i/n);return f.Arithmetic.round(u)},j=function W(t,r,n,e){if(n===t&&1===r||r===t&&1===n)return 1;if(n+r>t+1||t>r*n)return 0;var i,u,o=f.Arithmetic.add,l=f.Arithmetic.min(n,t-n-r+2),a=f.Arithmetic.max(1,f.Arithmetic.ceil((t-n)/(r-1))),c=0;for(null==e&&(e={}),i=a;l>=i;i++)u=t-n+","+(r-1)+","+i,null==e[u]&&(e[u]=W(t-n,r-1,i,e)),c=o(c,e[u]);return c},T=8,D=16,G=32,H=64,B=128,V=256,Y=512,K=T|D|G|H|B,z=V|Y,F=K|z,J=function(t){return arguments.length&&null!=t?t.substr?(t=t.toUpperCase(),f.ORDER[_](t)?f.ORDER[t]:T):F&t?t:T:T},Q=function(t){return arguments.length?function(){throw new Error('"'+t+'" not implemented')}:function(){throw new Error("Method not implemented")}};return f.ORDER={LEX:T,LEXICOGRAPHIC:T,REVLEX:D,ANTILEX:D,REVERSELEXICOGRAPHIC:D,ANTILEXICOGRAPHIC:D,COLEX:G,COLEXICOGRAPHIC:G,REVCOLEX:H,ANTICOLEX:H,REVERSECOLEXICOGRAPHIC:H,ANTICOLEXICOGRAPHIC:H,GRAY:B,MINIMAL:B,RANDOM:V,RANDOMISED:V,STOCHASTIC:Y},f.Util={rnd:Math.random,rint:function(t,r){return f.Arithmetic.round((r-t)*f.Util.rnd()+t)},shuffle:q,pick:E,operate:b,operation:w,map:y,intersection:x,union:k,kronecker:U,cartesian:C,num:function(t){return parseInt(t,10)},val:function(t){return f.Arithmetic.floor(t.valueOf())},equ:function(t,r){return t===r},gte:function(t,r){return t>=r},lte:function(t,r){return r>=t},gt:function(t,r){return t>r},lt:function(t,r){return r>t},add:function(t,r){return t+r},sub:function(t,r){return t-r},mul:function(t,r){return t*r},div:function(t,r){return f.Arithmetic.floor(t/r)},mod:function(t,r){return t%r},pow:Math.pow,shl:function(t,r){return t<>r},bor:function(t,r){return t|r},band:function(t,r){return t&r},neg:function(t){return f.Arithmetic.sub(0,t)},abs:Math.abs,min:Math.min,max:Math.max,floor:Math.floor,ceil:Math.ceil,round:Math.round,sum:M,product:L,pow2:S,powNK:N,factorial:P,binomial:X,partitions:j},f.Arithmetic={num:f.Util.num,val:f.Util.val,equ:f.Util.equ,gte:f.Util.gte,lte:f.Util.lte,gt:f.Util.gt,lt:f.Util.lt,add:f.Util.add,sub:f.Util.sub,mul:f.Util.mul,div:f.Util.div,mod:f.Util.mod,pow:f.Util.pow,shl:f.Util.shl,shr:f.Util.shr,bor:f.Util.bor,band:f.Util.band,neg:f.Util.neg,abs:f.Util.abs,min:f.Util.min,max:f.Util.max,floor:f.Util.floor,ceil:f.Util.ceil,round:f.Util.round,rnd:f.Util.rint},f.BitArray=v({constructor:function Z(t){var r=this;return r instanceof Z?(r.length=t,void(r.bits=new Uint32Array(f.Arithmetic.ceil(t/32)))):new Z(t)},length:0,bits:null,dispose:function(){var t=this;return t.length=null,t.bits=null,t},clone:function(){var t=this,r=new f.BitArray(t.length);return r.bits=new Uint32Array(t.bits),r},fromArray:function(t){var r=this;return r.bits=new Uint32Array(t),r},toArray:function(){return h.call(this.bits)},toString:function(){return y(this.toArray(),p).join("")},reset:function(){var t,r=this,n=r.bits,e=n.length;for(t=0;e>t;t++)n[t]=0;return r},isset:function(t){return!!(this.bits[t>>>5]&1<<(31&t))},set:function(t){var r=this;return r.bits[t>>>5]|=1<<(31&t),r},unset:function(t){var r=this;return r.bits[t>>>5]&=~(1<<(31&t)),r},toggle:function(t){var r=this;return r.bits[t>>>5]^=1<<(31&t),r}}),r=f.CombinatorialIterator=v({constructor:function $(t){var r,n=this;return n instanceof $?(r=n[s],n.n=t||0,n._count=r.count(n.n),void n.order(T)):new $(t)},__static__:{count:Q(),rank:Q(),unrank:Q(),first:Q(),last:Q(),stochastic:Q(),dual:function(t,r,n){return null==t?null:(T|D)&n?t.slice():O(I(t,r))},succ:function(t,r,n,e,i){var u=this,o=f.Arithmetic;return-1!==t&&1!==t&&(t=1),null==r?null:u.unrank(o.add(u.rank(r,n,e),t),n,e)},rand:function(t,r){var n=this,e=f.Arithmetic,i=r?r:n.count(t),u=e.sub(i,1),o=e.rnd(0,u);return e.equ(0,o)?n.first(t):e.equ(o,u)?n.last(t):n.unrank(o,t,i)}},n:0,_order:0,_count:0,_index:null,__item:null,_item:null,_prev:null,_next:null,_traversed:null,_stochastic:null,dispose:function(){var t=this;return t.n=null,t._order=null,t._count=0,t._index=null,t.__item=null,t._item=null,t._prev=null,t._next=null,t._stochastic=null,t._traversed&&(t._traversed.dispose(),t._traversed=null),t},_store:function(){var t=this;return[t._order,t._index,t.__item,t._item,t._prev,t._next]},_restore:function(t){var r=this;return t&&(r._order=t[0],r._index=t[1],r.__item=t[2],r._item=t[3],r._prev=t[4],r._next=t[5]),r},total:function(){return this._count},order:function(t,r,n,e){var i,u,o,l=this,a=l[s];if(!arguments.length)return l._order;if("object"==typeof r&&arguments.length<4?(e=n,n=r,r=!1):r=!1===r,t=J(t),l._order=t,l._index=0,l._item=l.__item=null,l._prev=!1,l._next=!1,u=l._count,o=l.n,Y&t)if(null==l._stochastic||n){if(!n)throw new Error("No Stochastic Transition Matrix given!");l._stochastic=[n,e?1:0,e?[]:null],l.__item=a.stochastic(l._stochastic[0],o,l._stochastic[2]),l._item=l.__item.slice()}else null!=l._stochastic[2]&&(l._stochastic[2]=[]),l.__item=a.stochastic(l._stochastic[0],o,l._stochastic[2]),l._item=l.__item.slice();else V&t?(l._traversed?l._traversed.reset():l._traversed=new f.BitArray(u),l._traversed.set(i=l.randomIndex()),l.__item=l.item(i,T),l._item=null==l.__item?null:l.__item.slice()):B&t?l._item=l.__item=null:H&t?(l.__item=r?a.last(o,H):a.first(o,H),l._item=a.dual(l.__item,o,H)):G&t?(l.__item=r?a.first(o,G):a.last(o,G),l._item=a.dual(l.__item,o,G)):D&t?(l.__item=r?a.first(o,D):a.last(o,D),l._item=a.dual(l.__item,o,D)):(l.__item=r?a.last(o,T):a.first(o,T),l._item=a.dual(l.__item,o,T));return l._prev=z&t||!r?!1:null!=l._item,l._next=!r||z&t?null!=l._item:!1,l},index:function(t){if(!arguments.length)return this._index;var r,n=this,e=f.Arithmetic,i=n[s],u=n.n,o=n._count,l=n._order;return t=e.num(t),e.gt(0,t)&&(t=e.add(t,o)),e.gte(t,0)&&e.lt(t,o)&&(r=e.sub(o,1),B&l?(n._index=t,n._item=n.__item=null):H&l?(n._index=t,n.__item=e.equ(0,t)?i.first(u,H):e.equ(r,t)?i.last(u,H):i.unrank(t,u,o),n._item=i.dual(n.__item,u,H)):G&l?(n._index=t,n.__item=e.equ(0,t)?i.last(u,G):e.equ(r,t)?i.first(u,G):i.unrank(e.sub(r,t),u,o),n._item=i.dual(n.__item,u,G)):D&l?(n._index=t,n.__item=e.equ(0,t)?i.last(u,D):e.equ(r,t)?i.first(u,D):i.unrank(e.sub(r,t),u,o),n._item=i.dual(n.__item,u,D)):T&l&&(n._index=t,n.__item=e.equ(0,t)?i.first(u,T):e.equ(r,t)?i.last(u,T):i.unrank(t,u,o),n._item=i.dual(n.__item,u,T))),n},randomIndex:function(t,r){var n=this,e=f.Arithmetic,i=n._count,u=arguments.length;return 0===u?(t=0,r=e.sub(i,1)):1===u?(t=e.num(t||0),r=e.sub(i,1)):(t=e.num(t),r=e.num(r)),e.rnd(t,r)},item:function(t,r){if(!arguments.length)return this._item;var n,e,i,u,o=this,l=o.n,a=o._count,c=o[s],_=f.Arithmetic;if(r=null!=r?J(r):o._order,t=_.num(t),_.gt(0,t)&&(t=_.add(t,a)),_.gte(t,0)&&_.lt(t,a)){if(n=_.sub(a,1),V&r){for(e=o._traversed,i=o.randomIndex(),u=f.Util.rnd()>.5?-1:1;e.isset(i);)i=_.add(i,u),_.lt(i,0)?i=n:_.gte(i,a)&&(i=0);return e.set(i),c.unrank(i,l,a)}return B&r?null:H&r?c.dual(_.equ(0,t)?c.first(l,H):_.equ(n,t)?c.last(l,H):c.unrank(t,l,a),l,H):G&r?c.dual(_.equ(0,t)?c.last(l,G):_.equ(n,t)?c.first(l,G):c.unrank(_.sub(n,t),l,a),l,G):D&r?c.dual(_.equ(0,t)?c.last(l,D):_.equ(n,t)?c.first(l,D):c.unrank(_.sub(n,t),l,a),l,D):c.dual(_.equ(0,t)?c.first(l,T):_.equ(n,t)?c.last(l,T):c.unrank(t,l,a),l,T)}return null},random:function(){var t=this,r=t[s];return r.rand(t.n,t._count)},rewind:function(){return this.order(this._order,!0)},forward:function(){return this.order(this._order,!1)},hasNext:function(){return Y&this._order?!0:this._next},hasPrev:function(){return z&this._order?!1:this._prev},next:function(){var t,r,n,e,i=this,u=f.Arithmetic,o=i._order,l=i[s],a=i._item,c=i.n,_=i._count;if(Y&o)i.__item=l.stochastic(i._stochastic[0],c,i._stochastic[2]),i._item=i.__item.slice();else if(V&o)if(n=u.sub(_,1),u.lt(i._index,n)){for(t=i._traversed,r=i.randomIndex(),e=f.Util.rnd()>.5?-1:1;t.isset(r);)r=u.add(r,e),u.lt(r,0)?r=n:u.gt(r,n)&&(r=0);t.set(r),i.__item=i.item(r,T),i._item=null==i.__item?null:i.__item.slice()}else i._item=i.__item=null,i._traversed&&(i._traversed.dispose(),i._traversed=null);else B&o?i._item=i.__item=null:H&o?(i.__item=l.succ(1,i.__item,c,_,H),i._item=l.dual(i.__item,c,H)):G&o?(i.__item=l.succ(-1,i.__item,c,_,G),i._item=l.dual(i.__item,c,G)):D&o?(i.__item=l.succ(-1,i.__item,c,_,D),i._item=l.dual(i.__item,c,D)):(i.__item=l.succ(1,i.__item,c,_,T),i._item=l.dual(i.__item,c,T));return i._next=null!=i._item,!i._next||Y&o||(i._index=u.add(i._index,1)),a},prev:function(){var t=this,r=f.Arithmetic,n=t._order,e=t[s],i=t._item,u=t.n,o=t._count;return z&n?null:(B&n?t._item=t.__item=null:H&n?(t.__item=e.succ(-1,t.__item,u,o,H),t._item=e.dual(t.__item,u,H)):G&n?(t.__item=e.succ(1,t.__item,u,o,G),t._item=e.dual(t.__item,u,G)):D&n?(t.__item=e.succ(1,t.__item,u,o,D),t._item=e.dual(t.__item,u,D)):(t.__item=e.succ(-1,t.__item,u,o,T),t._item=e.dual(t.__item,u,T)),t._prev=null!=t._item,!t._prev||z&n||(t._index=r.sub(t._index,1)),i)},range:function(t,r){var n,e,i,u,o,l=this,a=f.Arithmetic,c=l._count,s=1,_=arguments.length,h=a.sub(c,1);if(1>_?(t=0,r=h):2>_?(t=a.num(t),r=h):(t=a.num(t),r=a.num(r)),a.lt(t,0)&&(t=a.add(t,c)),a.lt(r,0)&&(r=a.add(r,c)),a.gt(t,r)&&(n=t,t=r,r=n,s=-1),a.lt(t,0)&&(t=0),a.gt(r,h)&&(r=h),a.lte(t,r)){if(o=l._store(),z&l._order||l.index(t),i=a.val(a.sub(r,t)),e=new Array(i+1),0>s)for(u=i;u>=0;u--)e[u]=l.next();else for(u=0;i>=u;u++)e[u]=l.next();l._restore(o)}else e=[];return e}}),n=f.Permutation=v(r,{constructor:function tt(t){var n=this;return n instanceof tt?void r.call(n,t):new tt(t)},__static__:{count:function(t){return P(t)},dual:r.dual,rank:function(t,r){var n,e,i,u,o=f.Arithmetic,l=0,a=o.ceil(g(r)),c=(1<<1+a)-1,s=new Array(c),_=o.shl(1,a);for(n=0;c>n;n++)s[n]=0;for(n=0;r>n;n++){for(u=t[n],i=o.val(o.add(_,u)),e=0;a>e;e++)1&i&&(u=o.sub(u,s[i>>>1<<1])),s[i]=o.add(s[i],1),i>>>=1;s[i]=o.add(s[i],1),l=o.add(o.mul(l,o.sub(n)),u)}return l},unrank:function(t,r,n){var e,i,u,o,l,a,c,s,_,h,d,m,v=f.Arithmetic,A=this;if(n=n||P(r),v.equ(0,t))return A.first(r);if(v.equ(n,v.add(t,1)))return A.last(r);for(e=new Array(r),i=v.div(n,r),_=v.ceil(g(r)),h=(1<<1+_)-1,d=new Array(h),m=v.shl(1,_),u=0;_>=u;u++)for(o=1,l=1<=o;o++)d[l-1+o]=v.shl(1,v.sub(_,u));for(s=r-1,u=0;r>u;u++){for(a=v.div(t,i),c=1,o=0;_>o;o++)d[c]=v.sub(d[c],1),c<<=1,v.gte(a,d[c])&&(a=v.sub(a,d[c]),c++);d[c]=0,e[u]=v.val(v.sub(c,m)),s&&(t=v.mod(t,i),i=v.div(i,s),s--)}return e},first:function(t){var r,n=new Array(t);for(r=0;t>r;r++)n[r]=r;return n},last:function(t){var r,n=new Array(t);for(r=0;t>r;r++)n[r]=t-1-r;return n},succ:function(t,r,n){if(r){var e,i,u,o,l,a=r.slice();if(-1===t){for(e=n-2;e>=0&&a[e]<=a[e+1];)e--;if(e>=0){for(i=n-1;i>e&&a[e]<=a[i];)i--;for(l=a[e],a[e]=a[i],a[i]=l,u=e+1,o=n-1;o>u;)l=a[u],a[u++]=a[o],a[o--]=l}else a=null}else{for(e=n-2;e>=0&&a[e]>=a[e+1];)e--;if(e>=0){for(i=n-1;i>e&&a[e]>=a[i];)i--;for(l=a[e],a[e]=a[i],a[i]=l,u=e+1,o=n-1;o>u;)l=a[u],a[u++]=a[o],a[o--]=l}else a=null}return a}return null},rand:function(t){var r,n=new Array(t);for(r=0;t>r;r++)n[r]=r;return q(n,!1,!1)},shuffle:function(t,r){return q(t,r,!1)},stochastic:function(t,r,n){if(t.length!==r||t[0].length!==r)throw new Error("Stochastic Matrix dimensions and Permutation dimensions do not match!");var e,i,u,o,l,a,c,s,_=new Array(r),h=new Array(r),d=0,m=f.Util.rnd,v=!1;for(i=0;r>i;i++)h[i]=0;if(n){if(v=!0,!n.length){for(n.N=0,e=new Array(r),i=0;r>i;i++)e[i]=0;for(i=0;r>i;i++)n.push(e.slice())}d=++n.N}for(s=!v,i=0;r>i;)for(o=m(),c=0,l=t[i],v&&(a=n[i]),u=0;r>u;u++){if(o>c&&o<=c+l[u]){0===h[u]&&(s||i+1===r||a[u]+1<=(d+1)*l[u])&&(h[u]=1,_[i]=u,v&&a[u]++,i++);break}c+=l[u]}return _},inverse:function(t,r){r=r||t.length;var n,e=new Array(r);for(n=0;r>n;n++)e[t[n]]=n;return e},compose:function(){var t,r,n,e=arguments,i=e.length,u=i?e[0]:[],o=u.length;for(r=1;i>r;r++)for(n=u.slice(),t=0;o>t;t++)u[t]=n[e[r][t]];return u},permute:function(t,r,n){var e,i,u,o=t.length;for(!0===n?(i=new Array(o),u=t):(i=t,u=t.slice()),e=0;o>e;e++)i[e]=u[r[e]];return i},reassign:function(t,r){var n,e=t.length,i=new Array(e);for(n=0;e>n;n++)i[n]=r[t[n]];return i},toCycles:function(t,r,n){r=r||t.length;var e,i,u,o=[],l=!0===n?1:0,a=new Array(r),f=new Array(r);for(e=0;r>e;e++)f[e]=e,a[e]=0;for(u=[i=f.shift()],a[i]=1;f.length;){if(i=t[i],a[i])for(u.length>l&&o.push(u),u=[];f.length&&a[i=f.shift()];);a[i]||(u.push(i),a[i]=1)}return u.length>l&&o.push(u),o},fromCycles:function(t,r){var n,e,i,u,o=new Array(r),l=t.length;for(e=0;r>e;e++)o[e]=e;for(n=0;l>n;n++)if(u=t[n],i=u.length,!(2>i)){for(e=0;i-1>e;e++)o[u[e]]=u[e+1];o[u[i-1]]=u[0]}return o},toSwaps:function(t,r){r=r||t.length;var e,i,u,o=[],l=n.toCycles(t,r,!0);for(e=0,i=l.length;i>e;e++)u=l[e],o=o.concat(R(u));return o},fromSwaps:function(t,r){var n,e,i,u=t.length,o=new Array(r);for(n=0;r>n;n++)o[n]=n;for(n=0;u>n;n++)e=t[n],i=o[e[0]],o[e[0]]=o[e[1]],o[e[1]]=i;return o},toMatrix:function(t,r,n){var e,i,u=new Array(r);for(n=!0===n,e=0;r>e;e++)for(u[e]=new Array(r),i=0;r>i;i++)u[e][i]=0;for(e=0;r>e;e++)n?u[t[e]][e]=1:u[e][t[e]]=1;return u},fromMatrix:function(t,r,n){var e,i,u=new Array(r);for(n=!0===n,e=0;r>e;e++)for(i=0;r>i;i++)t[e][i]&&(n?u[i]=e:u[e]=i);return u},isConnected:function(t,r){var n,e=-(1/0);for(r=r||t.length,n=0;r-1>n;n++)if(t[n]>e&&(e=t[n]),n>=e)return!1;return!0}}}),e=f.Combination=v(r,{constructor:function rt(t,n){var e=this;return e instanceof rt?void r.call(e,[t,n]):new rt(t,n)},__static__:{count:function(t){return X(t[0],t[1])},dual:function(t,n,e){return r.dual.call(this,t,n[0],e)},rank:function(t,r,n){var e,i,u,o,l,a=f.Arithmetic,c=0;for(o=r[1],r=r[0],l=n?n:X(r,o),e=1;o>=e;e++)i=r-1-t[e-1],u=o+1-e,i>=u&&(c=a.add(c,X(i,u)));return a.sub(a.sub(l,1),c)},unrank:function(t,r,n){var e,i,u,o,l,a,c=f.Arithmetic,s=this;if(n=n||X(r[0],r[1]),c.equ(0,t))e=s.first(r);else if(c.equ(n,c.add(t,1)))e=s.last(r);else{u=r[1],r=r[0],e=new Array(u),i=n,t=c.sub(c.sub(i,1),t),i=c.div(c.mul(i,c.sub(r,u)),r),l=r-u+1,o=u,a=r-1;do c.lte(i,t)?(e[u-o]=r-l-o+1,c.gt(i,0)&&(t=c.sub(t,i),i=c.div(c.mul(i,o),a)),o--,a--):(i=c.div(c.mul(i,c.sub(a,o)),a),l--,a--);while(o>0)}return e},first:function(t){var r,n=t[1],e=new Array(n);for(r=0;n>r;r++)e[r]=r;return e},last:function(t){var r,n=t[1],e=new Array(n);for(t=t[0],r=0;n>r;r++)e[n-1-r]=t-1-r;return e},succ:function(t,r,n){if(r){var e,i,u,o,l,a=r.slice();if(e=n[1],n=n[0],-1===t){for(i=e-1,u=-1;i>0;){if(a[i]>a[i-1]+1){u=i;break}i--}if(-1===u&&0-1){for(l=n,i=e-1;i>u;i--)a[i]=--l;a[u]--}else a=null}else{for(i=e-1,u=-1,o=n-e;i>=0;){if(a[i]-1)for(l=a[u],i=u;e>i;i++)a[i]=++l;else a=null}return a}return null},rand:function(t){var r,n,e,i,u,o,l,a;for(n=t[1],t=t[0],r=new Array(n),e=f.Util.rnd(),u=0,l=0,a=t-n,i=1;n>=i;i++){for(u++,o=(n-i+1)/(t-u+1);e>=o&&a+i>u;)l=o,u++,o=l+(1-l)*((n-i+1)/(t-u+1));r[i-1]=u-1,e=(e-l)/(o-l)}return r},stochastic:r.stochastic,complement:function(t,r){return I(t,r,!0)},pick:function(t,r){return E(t,r,!0)},choose:function(t,r){var n,e=r.length,i=new Array(e);for(n=0;e>n;n++)i[n]=t[r[n]];return i},toMatrix:function(t,r,n){var e,i,u,o;for(i=r[1],r=r[0],e=new Array(r),n=!0===n,u=0;r>u;u++)for(e[u]=new Array(r),o=0;r>o;o++)e[u][o]=0;for(u=0;i>u;u++)n?e[t[u]][u]=1:e[u][t[u]]=1;return e},fromMatrix:function(t,r,n){var e,i,u,o;for(i=r[1],r=r[0],e=new Array(i),n=!0===n,u=0;r>u;u++)for(o=0;r>o;o++)t[u][o]&&(n&&i>o?e[o]=u:!n&&i>u&&(e[u]=o));return e}}}),e.conjugate=e.complement,i=f.CombinationRepeat=v(r,{constructor:function nt(t,n){var e=this;return e instanceof nt?void r.call(e,[t,n]):new nt(t,n)},__static__:{count:function(t){return X(t[0]+t[1]-1,t[1])},dual:e.dual,rank:function(t,r,n){var e,i,u,o,l,a,c=f.Arithmetic,s=0;for(o=r[1],r=r[0],l=r+o-1,a=n?n:X(l,o),e=1;o>=e;e++)i=l-1-t[e-1]-e+1,u=o+1-e,i>=u&&(s=c.add(s,X(i,u)));return c.sub(c.sub(a,1),s)},unrank:function(t,r,n){var e,i,u,o,l,a,c,s=f.Arithmetic,_=this;if(n=n||X(r[0]+r[1]-1,r[1]),s.equ(0,t))return _.first(r);if(s.equ(n,s.add(t,1)))return _.last(r);u=r[1],r=r[0],o=r+u-1,e=new Array(u),i=n,t=s.sub(s.sub(i,1),t),i=s.div(s.mul(i,s.sub(o,u)),o),a=o-u+1,l=u,c=o-1;do s.lte(i,t)?(e[u-l]=o-a-u+1,s.gt(i,0)&&(t=s.sub(t,i),i=s.div(s.mul(i,l),c)),l--,c--):(i=s.div(s.mul(i,s.sub(c,l)),c),a--,c--);while(l>0);return e},first:function(t){var r,n=t[1],e=new Array(n);for(r=0;n>r;r++)e[r]=0;return e},last:function(t){var r,n=t[1],e=new Array(n);for(t=t[0]-1,r=0;n>r;r++)e[r]=t;return e},succ:function(t,r,n){if(r){var e,i,u,o,l=r.slice();if(e=n[1],n=n[0],-1===t){for(i=e-1,u=-1;i>0;){if(l[i]>l[i-1]){u=i;break}i--}if(-1===u&&0-1){for(o=n-1,i=u+1;e>i;i++)l[i]=o;l[u]--}else l=null}else{for(i=e-1,u=-1;i>=0;){if(l[i]-1)for(o=l[u]+1,i=u;e>i;i++)l[i]=o;else l=null}return l}return null},rand:function(t){var r,n,e,i,u,o,l,a,c;for(n=t[1],t=t[0],r=new Array(n),e=f.Util.rnd(),u=0,l=0,a=t+n-1,c=a-n,i=1;n>=i;i++){for(u++,o=(n-i+1)/(a-u+1);e>=o&&c+i>u;)l=o,u++,o=l+(1-l)*((n-i+1)/(a-u+1));r[i-1]=u-i,e=(e-l)/(o-l)}return r},stochastic:e.stochastic}}),u=f.Partition=v(r,{constructor:function et(t){var n=this;return n instanceof et?void r.call(n,t):new et(t)},__static__:{count:function(t){var r,n,e=f.Arithmetic.add,i=t>1?2:1;for(r=2;t>r;r++)for(n=t-r+1;n>=1;n--)i=e(i,j(t,r,n));return i},dual:function(t,r){if(null==t)return null;var n,e,i=[],u=t.length;for(n=0;u>n;n++)if(e=r-t[n],!(0>=e)){if(r===e)return[r];i.unshift(e)}return i},rank:function(t,r,n,e,i){var u,o,l,a=f.Arithmetic,c=this,s=t.length,_=r;return n=n||c.count(r),e=e||0,i=i||s,o=e,l=t[o],u=_===l?a.sub(n,1):1===l?0:s>o+1?a.add(1,c.rank(t,r-l,a.sub(n,c.count(r-l)),o+1)):0},unrank:function(t,r,n){return null},first:function(t){var r,n=new Array(t);for(r=0;t>r;r++)n[r]=1;return n},last:function(t){return[t]},succ:function(t,r,n){if(r){var e,i,u,o,l,a,f=r.slice();if(-1===t)if(f[0]>1){for(i=f.length,e=i-1;e>=0&&1===f[e];)e--;for(u=f[e]-1,f=f.slice(0,e+1),f[e]=u,l=M(f),a=n-l;a>0;)o=a,o>u?(o=u,f.push(o)):f.push(a),a-=o}else f=null;else if(f[0]0&&e--;e>0&&f[e]===f[e-1];)e--;for(f[e]++,f=f.slice(0,e+1),l=M(f),a=n-l;a>0;)f.push(1),a--}else f=null;return f}return null},rand:function(t,r){return null},stochastic:r.stochastic,conjugate:function(t){var r,n,e,i=t.length,u=t[0],o=new Array(u);for(r=0;u>r;r++)o[r]=1;for(n=1;i>n;n++)for(r=0,e=t[n];u>r&&e>0;)o[r++]++,e--;return o},pack:function(t){var r,n=[],e=t.length,i=t[0],u=[i,1];for(r=1;e>r;r++)i===t[r]?u[1]++:(n.push(u),i=t[r],u=[i,1]);return n.push(u),n},unpack:function(t){var r,n,e,i,u,o=[],l=t.length;for(r=0;l>r;r++)if(u=t[r],1===u[1])o.push(u[0]);else for(e=u[1],i=u[0],n=0;e>n;n++)o.push(i);return o}}}),u.transpose=u.conjugate,o=f.Powerset=f.Subset=v(r,{constructor:function it(t){var n=this;return n instanceof it?void r.call(n,t):new it(t)},__static__:{count:function(t){return S(t)},rank:function(t,r,n){for(var e=f.Arithmetic,i=0,u=0,o=t.length;o>u;)i=e.add(i,e.shl(1,t[u++]));return i},unrank:function(t,r,n){var e=this,i=f.Arithmetic,u=[],o=0;if(i.lt(t,0)||i.gte(t,n?n:e.count(r)))return null;for(;i.gt(t,0);)i.gt(i.band(t,1),0)&&u.push(o),i.gt(i.band(t,2),0)&&u.push(o+1),i.gt(i.band(t,4),0)&&u.push(o+2),i.gt(i.band(t,8),0)&&u.push(o+3),i.gt(i.band(t,16),0)&&u.push(o+4),i.gt(i.band(t,32),0)&&u.push(o+5),i.gt(i.band(t,64),0)&&u.push(o+6),i.gt(i.band(t,128),0)&&u.push(o+7),o+=8,t=i.shr(t,8);return u},rand:function(t,n){var e=r.rand.call(this,t,n);return null==e?null:e.reverse()},stochastic:r.stochastic,dual:function(t,r,n){return null==t?null:(G|H|z)&n?t.slice():O(I(t,r,!0))},first:function(t,r){var n,e=new Array(t);for(n=0;t>n;n++)e[n]=n;return e},last:function(t,r){return[]},succ:function(t,n,e,i,u){return-1!==t&&1!==t&&(t=1),null==n?null:r.succ.call(this,-t,n,e,i,u)}}}),l=f.Tensor=v(r,{constructor:function ut(){var t=this;return t instanceof ut?void(arguments.length?r.call(t,h.call(arguments)):(t.n=[],t._count=0)):(t=new ut,arguments.length?r.call(t,h.call(arguments)):(t.n=[],t._count=0),t)},__static__:{count:function(t){return t&&t.length?L(t):0},dual:function(t,r,n){return(T|D)&n?null==t?null:t.slice():null==t?null:I(t,r,!1,!0)},rank:function(t,r){var n,e,i=f.Arithmetic,u=r,o=u.length;if(!o)return-1;for(n=0,e=0;o>e;e++)n=i.add(i.mul(n,u[e]),t[e]);return n},unrank:function(t,r){var n,e,i,u,o,l=f.Arithmetic,a=r,c=a.length;if(!c)return[];for(o=new Array(c),n=t,i=c-1;i>=0;i--)e=a[i],u=l.mod(n,e),n=l.div(n,e),o[i]=l.val(u);return o},first:function(t){var r,n=t.length,e=new Array(n);for(r=0;n>r;r++)e[r]=0;return e},last:function(t){var r,n=t,e=n.length,i=new Array(e);for(r=0;e>r;r++)i[r]=n[r]-1;return i},succ:function(t,r,n){if(r){var e,i,u=r.slice(),o=n,l=o.length;if(-1===t){for(e=l-1;e>=0&&u[e]-1<0;)e--;if(e>=0)for(u[e]--,i=e+1;l>i;i++)u[i]=o[i]-1;else u=null}else{for(e=l-1;e>=0&&u[e]+1===o[e];)e--;if(e>=0)for(u[e]++,i=e+1;l>i;i++)u[i]=0;else u=null}return u}return null},rand:function(t){var r,n=f.Arithmetic.rnd,e=t,i=e.length,u=new Array(i);for(r=0;i>r;r++)u[r]=n(0,e[r]-1);return u},stochastic:r.stochastic,product:U,component:function(t,r){var n,e,i,u,o,l,a=[],f=r,c=f.length;for(n=0;c>n;n++)if(i=f[n],o=t[n],u=i[o],u instanceof Array)for(e=0,l=u.length;l>e;e++)a.push(u[e]);else a.push(u);return a}}}),a=f.Tuple=v(r,{constructor:function ot(t,n){var e=this;return e instanceof ot?void r.call(e,[t||1,n||2]):new ot(t,n)},__static__:{count:function(t){return N(t[1],t[0])},dual:function(t,r,n){return(T|D)&n?null==t?null:t.slice():O(I(t,r[1]))},rank:function(t,r){var n,e,i=f.Arithmetic,u=r[0];for(r=r[1],n=0,e=0;u>e;e++)n=i.add(i.mul(n,r),t[e]);return n},unrank:function(t,r){var n,e,i,u,o,l=f.Arithmetic,a=r[0];for(r=r[1],o=new Array(a),n=t,i=a-1;i>=0;i--)e=r,u=l.mod(n,e),n=l.div(n,e),o[i]=l.val(u);return o},first:function(t){var r,n=t[0],e=new Array(n);for(r=0;n>r;r++)e[r]=0;return e},last:function(t){var r,n=t[0],e=new Array(n);for(t=t[1]-1,r=0;n>r;r++)e[r]=t;return e},succ:function(t,r,n){if(r){var e,i,u=r.slice(),o=n[0],n=n[1];if(-1===t){for(e=o-1;e>=0&&u[e]-1<0;)e--;if(e>=0)for(u[e]--,i=e+1;o>i;i++)u[i]=n-1;else u=null}else{for(e=o-1;e>=0&&u[e]+1===n;)e--;if(e>=0)for(u[e]++,i=e+1;o>i;i++)u[i]=0;else u=null}return u}return null},rand:function(t){var r,n=f.Arithmetic.rnd,e=t[0],i=new Array(e);for(t=t[1]-1,r=0;e>r;r++)i[r]=n(0,t);return i},stochastic:l.stochastic}}),f}); \ No newline at end of file +!function(n,t,r){"use strict";var e;"undefined"!=typeof Components&&"object"==typeof Components.classes&&"object"==typeof Components.classesByID&&Components.utils&&"function"==typeof Components.utils["import"]?(n.EXPORTED_SYMBOLS=[t])&&(n[t]=r.call(n)):"object"==typeof module&&module.exports?module.exports=r.call(n):"function"==typeof define&&define.amd&&"function"==typeof require&&"function"==typeof require.specified&&require.specified(t)?define(t,["require","exports","module"],function(){return r.call(n)}):t in n||(n[t]=e=r.call(n))&&"function"==typeof define&&define.amd&&define(function(){return e})}(this,"Abacus",function(t){"use strict";var r,e,i,u,o,l,a,f={VERSION:"0.1.0"},c="prototype",s="constructor",_="hasOwnProperty",h=function(){throw new Error("Method not implemented!")},d=Array.prototype.slice,m=Object[c].toString,v=Object.create,A=function(n,t){for(var r in t)t[_](r)&&(n[r]=t[r]);return n},g=function(n,t){1===arguments.length&&(t=n,n=Object);var r=t[s];return t[_]("__static__")&&(r=A(r,t.__static__),delete t.__static__),r[c]=A(v(n[c]),t),r},p=Math.log2||function(n){return Math.log(n)/Math.LN2},x=function(n){return function(t){var r,e;return e=t.toString(2),(r=n-e.length)>0&&(e=new Array(r+1).join("0")+e),e}},y=x(32),w=function(n,t,r,e){if(r>e)return t;var i,u,o=e-r+1,l=15&o,a=1&l,f=a?n(t,r):t;for(i=a;l>i;i+=2)u=r+i,f=n(n(f,u),u+1);for(i=l;o>i;i+=16)u=r+i,f=n(n(n(n(n(n(n(n(n(n(n(n(n(n(n(n(f,u),u+1),u+2),u+3),u+4),u+5),u+6),u+7),u+8),u+9),u+10),u+11),u+12),u+13),u+14),u+15);return f},M=function(n,t,r,e,i,u){var o=n.length;if(arguments.length<5&&(i=o-1),0>i&&(i+=o),arguments.length<4&&(e=0),e>i)return r;if(!0===u){var l,a,f=i-e+1,c=f-1,s=15&f,_=1&s,h=c-s,d=_?t(r,n[i],i):r;for(l=c-_;l>h;l-=2)a=e+l,d=t(t(d,n[a],a),n[a-1],a-1);for(l=h;l>=0;l-=16)a=e+l,d=t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(d,n[a],a),n[a-1],a-1),n[a-2],a-2),n[a-3],a-3),n[a-4],a-4),n[a-5],a-5),n[a-6],a-6),n[a-7],a-7),n[a-8],a-8),n[a-9],a-9),n[a-10],a-10),n[a-11],a-11),n[a-12],a-12),n[a-13],a-13),n[a-14],a-14),n[a-15],a-15)}else{var l,a,f=i-e+1,s=15&f,_=1&s,d=_?t(r,n[e],e):r;for(l=_;s>l;l+=2)a=e+l,d=t(t(d,n[a],a),n[a+1],a+1);for(l=s;f>l;l+=16)a=e+l,d=t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(d,n[a],a),n[a+1],a+1),n[a+2],a+2),n[a+3],a+3),n[a+4],a+4),n[a+5],a+5),n[a+6],a+6),n[a+7],a+7),n[a+8],a+8),n[a+9],a+9),n[a+10],a+10),n[a+11],a+11),n[a+12],a+12),n[a+13],a+13),n[a+14],a+14),n[a+15],a+15)}return d},b=function(n,t,r,e,i){var u=n.length;if(arguments.length<4&&(e=u-1),0>e&&(e+=u),arguments.length<3&&(r=0),r>e)return[];var o,l,a,f,c,s,_=e-r+1,h=new Array(_);if(!0===i){for(a=_-1,c=15&_,s=1&c,f=a-c,s&&(h[0]=t(n[e],e,r,e)),o=a-s;o>f;o-=2)l=r+o,h[o]=t(n[l],l,r,e),h[o+1]=t(n[l-1],l-1,r,e);for(o=f;o>=0;o-=16)l=r+o,h[o]=t(n[l],l,r,e),h[o+1]=t(n[l-1],l-1,r,e),h[o+2]=t(n[l-2],l-2,r,e),h[o+3]=t(n[l-3],l-3,r,e),h[o+4]=t(n[l-4],l-4,r,e),h[o+5]=t(n[l-5],l-5,r,e),h[o+6]=t(n[l-6],l-6,r,e),h[o+7]=t(n[l-7],l-7,r,e),h[o+8]=t(n[l-8],l-8,r,e),h[o+9]=t(n[l-9],l-9,r,e),h[o+10]=t(n[l-10],l-10,r,e),h[o+11]=t(n[l-11],l-11,r,e),h[o+12]=t(n[l-12],l-12,r,e),h[o+13]=t(n[l-13],l-13,r,e),h[o+14]=t(n[l-14],l-14,r,e),h[o+15]=t(n[l-15],l-15,r,e)}else{for(c=15&_,s=1&c,s&&(h[0]=t(n[r],r,r,e)),o=s;c>o;o+=2)l=r+o,h[o]=t(n[l],l,r,e),h[o+1]=t(n[l+1],l+1,r,e);for(o=c;_>o;o+=16)l=r+o,h[o]=t(n[l],l,r,e),h[o+1]=t(n[l+1],l+1,r,e),h[o+2]=t(n[l+2],l+2,r,e),h[o+3]=t(n[l+3],l+3,r,e),h[o+4]=t(n[l+4],l+4,r,e),h[o+5]=t(n[l+5],l+5,r,e),h[o+6]=t(n[l+6],l+6,r,e),h[o+7]=t(n[l+7],l+7,r,e),h[o+8]=t(n[l+8],l+8,r,e),h[o+9]=t(n[l+9],l+9,r,e),h[o+10]=t(n[l+10],l+10,r,e),h[o+11]=t(n[l+11],l+11,r,e),h[o+12]=t(n[l+12],l+12,r,e),h[o+13]=t(n[l+13],l+13,r,e),h[o+14]=t(n[l+14],l+14,r,e),h[o+15]=t(n[l+15],l+15,r,e)}return h},C=function(){var n,t,r,e,i,u,o,l,a,f,c=arguments,s=c.length;if(!s)return[];for(a=c[0].length,n=1;s>n;n++)a*=c[n].length;for(f=new Array(a),n=0;a>n;n++){for(l=[],r=n,t=s-1;t>=0;t--)if(e=c[t].length,i=r%e,r=~~(r/e),o=c[t][i],o instanceof Array)for(u=o.length-1;u>=0;u--)l.unshift(o[u]);else l.unshift(o);f[n]=l}return f},E=function(){var n,t,r,e,i,u,o,l=arguments,a=l.length;if(!a)return[];for(u=l[0].length,n=1;a>n;n++)un;n++){for(r=[],t=a-1;t>=0;t--)if(e=l[t].length=0;i--)r.unshift(e[i]);else r.unshift(e);o[n]=r}return o},I=function(n,t,r){r=-1===r?1:0;for(var e=0,i=0,u=n.length,o=t.length,l=new Array(f.Math.min(u,o)),a=0;u>e&&o>i;)n[e]t[i]?r?e++:i++:(l[a++]=n[e],e++,i++);return au&&a>o;){if(e&&c){if(n[u]===i){u++;continue}if(t[o]===i){o++;continue}}n[u]t[o]?f[c++]=i=r?n[u++]:t[o++]:(f[c++]=i=n[u],s&&(f[c++]=t[o]),u++,o++)}for(;l>u;)(s||n[u]!==i)&&(f[c++]=i=n[u++]);for(;a>o;)(s||t[o]!==i)&&(f[c++]=i=t[o++]);return c=n[e?0:l-1])e?n.unshift(t):n.push(t);else{if(i=0,o=l-1,e)for(;o>i;)u=i+(o-i+1>>>1),ri;)u=i+(o-i+1>>>1),re;)i>=u||ee;e++)for(h=t[e],i=0,o=h.length;o>i;i++)a[l[c=d(0,r-1-s)]]=h[i],c!==r-1-s&&(_=l[r-1-s],l[r-1-s]=l[c],l[c]=_),s++;return a},S=function(n,t,r,e,i){var u,o,l,a,c,s=f.Math.rndInt,_=n.length;if(t=f.Math.min(t,_),e=!0===e,!0===r){if(_-=1,e)for(u=[],l=0;t>l;l++)R(u,n[s(0,_)]);else for(u=new Array(t),l=0;t>l;l++)u[l]=n[s(0,_)];return u}if(i=!1!==i,i&&(o=new Array(t)),e)for(u=[],l=0;t>l;l++)a=s(0,--_),c=n[a],n[a]=n[_],n[_]=c,R(u,c),i&&(o[l]=a);else for(u=new Array(t),l=0;t>l;l++)a=s(0,--_),c=n[a],n[a]=n[_],n[_]=c,u[l]=c,i&&(o[l]=a);if(i)for(l=t-1;l>=0;l--)a=o[l],c=n[_],n[_]=n[a],n[a]=c,_++;return u},q=function(n,t){if(null==n)return null;if(n instanceof Array){var r,e=n.length,i=new Array(e),u=0;if(t instanceof Array)for(r=e-1;r>=0;r--)i[r]=t[r]>0?(n[r]+u)%t[r]:0,u=u+t[r]-i[r];else for(r=e-1;r>=0;r--)i[r]=(n[r]+u)%t,u=u+t-i[r];return i}return n=f.Arithmetic.N(n),f.Arithmetic.xor(n,f.Arithmetic.shr(n,f.Arithmetic.I))},G=function(n){return null==n?null:n.slice()},X=function(n,t){if(null==n)return null;if(!n.length)return[];var r,e=n.length,i=new Array(e);if(t instanceof Array)for(r=0;e>r;r++)i[r]=t[r]-1-n[r];else for(t-=1,r=0;e>r;r++)i[r]=t-n[r];return i},j=function(n){if(null==n)return null;var t,r=n.length-1,e=new Array(r+1);for(t=0;r>=t;t++)e[t]=n[r-t];return e},D=function(n,t){if(null==t&&(t=0),n instanceof Array){var r,e=n.length,i=new Array(e);for(r=0;e>r;r++)i[r]=t-n[r];return i}return"number"==typeof n&&"number"==typeof t?t-n:f.Arithmetic.sub(f.Arithmetic.N(t),n)},V=function(n,t){if(null==n)return null;var r,e,i,u,o=n.length,l=t-o;if(0>=t||0>=l)return[];for(r=new Array(l),e=0,i=0,u=0;l>u;)i>=o||et;t++)o[t]=1;for(r=1;i>r;r++)for(t=0,e=n[r];u>t&&e>0;)o[t++]++,e--;return o},H=function(n){var t,r,e,i,u,o,l=n.length;for(t=new Array(l),o=0,i=0;l>i;i++){for(r=new Array(u=n[i]),e=0;u>e;e++)r[e]=o++;t[i]=r}return t},B=function(n){var t,r,e=n.length;for(t=new Array(e),r=0;e>r;r++)t[r]=n[r].length;return t},U=function(n){var t,r=[],e=n.length;if(e>1)for(t=e-1;t>=1;t--)r.push([n[0],n[t]]);return r},Y=function(n){return M(n,f.Arithmetic.add,f.Arithmetic.O)},z=function(n){return M(n,f.Arithmetic.mul,f.Arithmetic.I)},J=function(n){var t=f.Arithmetic;return t.shl(t.I,t.N(n))},K=function(n,t){var r=f.Arithmetic;return r.pow(r.N(n),r.N(t))},Q=function(n){var t=f.Arithmetic,r=t.O,e=t.I;return n=t.N(n),t.lt(n,0)?r:t.lt(n,2)?e:t.lt(n,4)?t.shl(n,t.sub(n,2)):w(t.mul,e,2,n)},W=function(n,t){var r=f.Arithmetic,e=r.O,i=r.I;if(t>n-t&&(t=n-t),0>t||1>n)return e;if(0===t||1===n)return i;if(1===t)return n;var u,o=r.mul,l=n-t,a=r.N(1+l);for(u=2;t>=u;u++)a=o(a,1+l/u);return r.round(a)},Z=function(n){var t,r=f.Arithmetic,e=f.Math.Factorial,i=n instanceof Array?n:arguments,u=e(i[0]),o=i.length,l=r.I,a=r.mul,c=r.div;for(t=1;o>t;t++)l=a(l,e(i[t]));return c(u,l)},$={},nn=function hn(n,t,r){var e=f.Arithmetic,i=e.O,u=e.I;if(r===n&&1===t||t===n&&1===r)return u;if(r+t>n+1||n>t*r)return i;var o,l,a=f.Math,c=e.add,s=a.min(r,n-r-t+2),_=a.max(1,a.ceil((n-r)/(t-1))),h=i;for(o=_;s>=o;o++)l=n-r+","+(t-1)+","+o,null==$[l]&&($[l]=hn(n-r,t-1,o)),h=c(h,$[l]);return h},tn=1,rn=2,en=4,un=8,on=16,ln=32,an=64,fn=en|un|on,cn=ln|an,sn=fn|cn|tn|rn,_n=function(n){if(!arguments.length||null==n)return en;if("string"==typeof n){for(var t=0,r=n.toUpperCase().split(","),e=0,i=r.length;i>e;e++)n=r[e],t|=f.ORDER[_](n)?f.ORDER[n]:0;return t>0?t:en}return sn&n?n:en};return f.ORDER={LEX:en,LEXICOGRAPHIC:en,REVLEX:en|tn,ANTILEX:en|tn,REVERSELEXICOGRAPHIC:en|tn,ANTILEXICOGRAPHIC:en|tn,REFLEX:en|rn,REFLECTEDLEXICOGRAPHIC:en|rn,COLEX:un,COLEXICOGRAPHIC:un,REVCOLEX:un|tn,ANTICOLEX:un|tn,REVERSECOLEXICOGRAPHIC:un|tn,ANTICOLEXICOGRAPHIC:un|tn,REFCOLEX:un|rn,REFLECTEDCOLEXICOGRAPHIC:un|rn,REV:tn,REVERSE:tn,REVERSED:tn,REF:rn,REFLECT:rn,REFLECTED:rn,GRAY:on,MINIMAL:on,RANDOM:ln,RANDOMISED:ln,STOCHASTIC:an},f.List={operate:M,map:b,operation:w,sum:Y,product:z,kronecker:C,cartesian:E,intersection:I,union:O,insertion:R,shuffle:P,xshuffle:N,multiset_shuffle:L,pick:S},f.Math={O:0,I:1,N:function(n){return f.Arithmetic.add(f.Arithmetic.O,n)},V:function(n){return f.Arithmetic.sub(f.Arithmetic.O,n)},rnd:Math.random,rndInt:function(n,t){return f.Math.round((t-n)*f.Math.rnd()+n)},equ:function(n,t){return n===t},gte:function(n,t){return n>=t},lte:function(n,t){return t>=n},gt:function(n,t){return n>t},lt:function(n,t){return t>n},inside:function(n,t,r,e){return e?n>=t&&r>=n:n>t&&r>n},clamp:function(n,t,r){return t>n?t:n>r?r:n},wrap:function(n,t,r){return t>n?r:n>r?t:n},wrapR:function(n,t){return 0>n?n+t:n},add:function(n,t){return n+t},sub:function(n,t){return n-t},mul:function(n,t){return n*t},div:function(n,t){return f.Math.floor(n/t)},mod:function(n,t){return n%t},pow:Math.pow,shl:function(n,t){return n<>t},bor:function(n,t){return n|t},band:function(n,t){return n&t},xor:function(n,t){return n^t},abs:Math.abs,min:Math.min,max:Math.max,floor:Math.floor,ceil:Math.ceil,round:Math.round,num:function(n){return"number"==typeof n?f.Math.floor(n):parseInt(n,10)},val:function(n){return f.Math.floor(n.valueOf())},Pow2:J,Exp:K,Factorial:Q,Binomial:W,Multinomial:Z,Partitions:nn},f.Arithmetic={O:0,I:1,N:f.Math.N,V:f.Math.V,equ:f.Math.equ,gte:f.Math.gte,lte:f.Math.lte,gt:f.Math.gt,lt:f.Math.lt,inside:f.Math.inside,clamp:f.Math.clamp,wrap:f.Math.wrap,wrapR:f.Math.wrapR,add:f.Math.add,sub:f.Math.sub,mul:f.Math.mul,div:f.Math.div,mod:f.Math.mod,pow:f.Math.pow,shl:f.Math.shl,shr:f.Math.shr,bor:f.Math.bor,band:f.Math.band,xor:f.Math.xor,abs:f.Math.abs,min:f.Math.min,max:f.Math.max,floor:f.Math.floor,ceil:f.Math.ceil,round:f.Math.round,rnd:f.Math.rndInt,num:f.Math.num,val:f.Math.val},f.BitArray=g({constructor:function dn(n){var t=this;return t instanceof dn?(t.length=n,void(t.bits=new Uint32Array(f.Math.ceil(n/32)))):new dn(n)},length:0,bits:null,dispose:function(){var n=this;return n.length=null,n.bits=null,n},clone:function(){var n=this,t=new f.BitArray(n.length);return t.bits=new Uint32Array(n.bits),t},fromArray:function(n){var t=this;return t.bits=new Uint32Array(n),t},toArray:function(){return d.call(this.bits)},toString:function(){return b(this.toArray(),y).join("")},reset:function(){var n,t=this,r=t.bits,e=r.length;for(n=0;e>n;n++)r[n]=0;return t},isset:function(n){return!!(this.bits[n>>>5]&1<<(31&n))},set:function(n){var t=this;return t.bits[n>>>5]|=1<<(31&n),t},unset:function(n){var t=this;return t.bits[n>>>5]&=~(1<<(31&n)),t},toggle:function(n){var t=this;return t.bits[n>>>5]^=1<<(31&n),t}}),r=f.CombinatorialIterator=g({constructor:function(n,t){var r=this,e=r[s];r.n=n||0,r._count=e.count(r.n),r.order(t?t:en)},__static__:{Iterable:function mn(n){return this instanceof mn?void(this.next=function(){return n.hasNext()?{value:n.next()}:{done:!0}}):new mn(n)},C:function(n,t){return X(n,t)},P:function(n,t){return j(n)},T:function(n,t){return D(n,t)},G:function(n,t){return q(n,t)},count:h,rand:function(n,t){var r=this,e=f.Arithmetic,i=null!=t?t:r.count(n);return r.unrank(e.rnd(e.O,e.sub(i,1)),n,i)},stochastic:h,rank:h,unrank:h},n:0,_order:0,_count:0,__index:null,_index:null,__item:null,_item:null,_prev:null,_next:null,_traversed:null,_stochastic:null,dispose:function(){var n=this;return n.n=null,n._order=null,n._count=0,n.__index=null,n._index=null,n.__item=null,n._item=null,n._prev=null,n._next=null,n._stochastic=null,n._traversed&&(n._traversed.dispose(),n._traversed=null),n},_store:function(){var n=this;return[n._order,n.__index,n._index,n.__item,n._item,n._prev,n._next,n.n]},_restore:function(n){var t=this;return n&&(t._order=n[0],t.__index=n[1],t._index=n[2],t.__item=n[3],t._item=n[4],t._prev=n[5],t._next=n[6],t.n=n[7]),t},total:function(){return this._count},order:function(n,t,r,e){var i,u,o,l,a,c=this,_=f.Arithmetic,h=_.O,d=c[s],m=d.T;if(!arguments.length)return c._order;if("object"==typeof t&&arguments.length<4?(e=r,r=t,t=!1):t=!1===t,n=_n(n),u=c._count,l=c.n,o=_.sub(u,1),a=tn&n?m(1):1,a=t?m(a):a,c._order=n,c.__index=c._index=h,c._item=c.__item=null,c._prev=!1,c._next=!1,an&n)if(null==c._stochastic||r){if(!r)throw new Error("No Stochastic Transition Matrix given!");c._stochastic=[r,e?1:0,e?[]:null],c.__item=d.stochastic(c._stochastic[0],l,c._stochastic[2])}else null!=c._stochastic[2]&&(c._stochastic[2]=[]),c.__item=d.stochastic(c._stochastic[0],l,c._stochastic[2]);else ln&n?(_.gt(u,1e5)?(c._traversed&&(c._traversed.dispose(),c._traversed=null),i=c.randomIndex()):(c._traversed?c._traversed.reset():c._traversed=new f.BitArray(u),c._traversed.set(i=c.randomIndex())),c.__item=d.unrank(i,l,u),null!=c.__item&&(c.__index=i)):on&n?(c.__item=c.item0(m(a),n),null!=c.__item&&(c.__index=-1===a?h:m(h,o))):un&n?(c.__item=c.item0(m(a),n),null!=c.__item&&(c.__index=-1===a?h:m(h,o))):(c.__item=c.item0(a,n),null!=c.__item&&(c.__index=-1===a?m(h,o):h));return c._item=null==c.__item?null:c.dual(c.__item,an&n?null:c.__index,n),c._index=!t||cn&n?h:m(h,o),c._prev=cn&n||!t?!1:null!=c.__item,c._next=!t||cn&n?null!=c.__item:!1,c},index:function(n){if(!arguments.length)return this._index;var t,r=this,e=f.Arithmetic,i=e.O,u=r[s],o=u.T,l=r.n,a=r._count,c=r._order,_=tn&c?o(1):1;return n=e.wrapR(e.N(n),a),!e.equ(n,r._index)&&e.inside(n,-1,a)&&(t=e.sub(a,1),on&c?(r.__index=-1===_?n:o(n,t),r._index=n,r.__item=e.equ(i,n)?r.item0(o(_),c):e.equ(t,n)?r.item0(_,c):u.unrank(r.__index,l,a),r._item=r.dual(r.__item,r.__index,c),r._prev=null!=r.__item,r._next=null!=r.__item):un&c?(r.__index=-1===_?n:o(n,t),r._index=n,r.__item=e.equ(i,n)?r.item0(o(_),c):e.equ(t,n)?r.item0(_,c):u.unrank(r.__index,l,a),r._item=r.dual(r.__item,r.__index,c),r._prev=null!=r.__item,r._next=null!=r.__item):cn&c||(r.__index=-1===_?o(n,t):n,r._index=n,r.__item=e.equ(i,n)?r.item0(_,c):e.equ(t,n)?r.item0(o(_),c):u.unrank(r.__index,l,a),r._item=r.dual(r.__item,r.__index,c),r._prev=null!=r.__item,r._next=null!=r.__item)),r},item:function(n,t){if(!arguments.length)return this._item;var r,e,i,u=this,o=u.n,l=u._count,a=u[s],c=a.T,_=f.Arithmetic,h=_.O;return t=null!=t?_n(t):u._order,n=_.wrapR(_.N(n),l),t===u._order&&_.equ(n,u._index)?u._item:_.inside(n,-1,l)?(e=tn&t?-1:1,r=_.sub(l,1),ln&t?(i=u.randomIndex(),u.dual(a.unrank(i,o,l),i,t)):on&t?(i=-1===e?n:c(n,r),u.dual(_.equ(h,n)?u.item0(c(e),t):_.equ(r,n)?u.item0(e,t):a.unrank(i,o,l),i,t)):un&t?(i=-1===e?n:c(n,r),u.dual(_.equ(h,n)?u.item0(c(e),t):_.equ(r,n)?u.item0(e,t):a.unrank(i,o,l),i,t)):(i=-1===e?c(n,r):n,u.dual(_.equ(h,n)?u.item0(e,t):_.equ(r,n)?u.item0(c(e),t):a.unrank(i,o,l),i,t))):null},dual:function(n,t,r){if(null==n)return null;r=r||0;var e=this,i=e[s],u=e.n,o=i.C,l=i.P,a=(i.T,i.G),f=rn&r;return cn&r?f?l(n,u):n:on&r?f?a(l(o(n,u),u),u):l(a(l(o(n,u),u),u),u):un&r?f?o(n,u):l(o(n,u),u):f?l(n,u):G(n)},randomIndex:function(n,t){var r=this,e=f.Arithmetic,i=e.N,u=e.O,o=r._count,l=arguments.length;return 0===l?(n=u,t=e.sub(o,1)):1===l?(n=i(n||0),t=e.sub(o,1)):(n=i(n),t=i(t)),e.rnd(n,t)},random:function(){var n=this,t=n[s];return n.dual(t.rand(n.n,n._count),null,ln|n._order)},rewind:function(){return this.order(this._order,!0)},forward:function(){return this.order(this._order,!1)},hasNext:function(){return an&this._order?!0:this._next},hasPrev:function(){return cn&this._order?!1:this._prev},item0:h,succ:function(n,t,r,e){var i=this,u=i[s],o=f.Arithmetic,l=i._count,a=i.n;return null==t?null:u.unrank(o.add(r,-1===n?-1:1),a,l)},next:function(){var n,t,r,e,i,u=this,o=f.Arithmetic,l=o.O,a=u._order,c=u[s],_=c.T,h=u._item,d=u.n,m=u._count;if(an&a)u.__item=c.stochastic(u._stochastic[0],d,u._stochastic[2]);else if(ln&a)if(n=u._traversed)if(e=o.sub(m,1),o.lt(u._index,e)){for(t=u.randomIndex(),i=f.Math.rnd()>.5?-1:1;n.isset(t);)t=o.wrap(o.add(t,i),l,e);n.set(t),u.__item=c.unrank(t,d,m),null!=u.__item&&(u.__index=t)}else u._item=u.__item=null,u._traversed&&(u._traversed.dispose(),u._traversed=null);else t=u.randomIndex(),u.__item=c.unrank(t,d,m),null!=u.__item&&(u.__index=t);else r=tn&a?_(1):1,on&a?(u.__item=u.succ(_(r),u.__item,u.__index,a),null!=u.__item&&(u.__index=o.add(u.__index,_(r)))):un&a?(u.__item=u.succ(_(r),u.__item,u.__index,a),null!=u.__item&&(u.__index=o.add(u.__index,_(r)))):(u.__item=u.succ(r,u.__item,u.__index,a),null!=u.__item&&(u.__index=o.add(u.__index,r)));return u._item=null==u.__item?null:u.dual(u.__item,an&a?null:u.__index,a),u._next=null!=u.__item,!u._next||an&a||(u._index=o.add(u._index,1)),h},prev:function(){var n,t=this,r=f.Arithmetic,e=t._order,i=t[s],u=i.T,o=t._item;t.n,t._count;return cn&e?null:(n=tn&e?u(1):1,on&e?(t.__item=t.succ(n,t.__item,t.__index,e),null!=t.__item&&(t.__index=r.add(t.__index,n))):un&e?(t.__item=t.succ(n,t.__item,t.__index,e),null!=t.__item&&(t.__index=r.add(t.__index,n))):(t.__item=t.succ(u(n),t.__item,t.__index,e),null!=t.__item&&(t.__index=r.add(t.__index,u(n)))),t._item=null==t.__item?null:t.dual(t.__item,t.__index,e),t._prev=null!=t.__item,t._prev&&(t._index=r.sub(t._index,1)),o)},range:function(n,t){var r,e,i,u,o,l=this,a=f.Arithmetic,c=a.N,s=a.O,_=l._count,h=1,d=arguments.length,m=a.sub(_,1),v=!(cn&l._order);if(1>d?(n=s,t=m):2>d?(n=c(n),t=m):(n=c(n),t=c(t)),n=a.wrapR(n,_),t=a.wrapR(t,_),a.gt(n,t)&&(r=n,n=t,t=r,h=-1),n=a.clamp(n,s,m),v&&(t=a.clamp(t,s,m)),a.lte(n,t)){if(o=l._store(),v&&l.index(n),i=a.val(a.sub(t,n)),e=new Array(i+1),0>h)for(u=i;u>=0;u--)e[u]=l.next();else for(u=0;i>=u;u++)e[u]=l.next();l._restore(o)}else e=[];return e},__iter__:function(){return new r.Iterable(this)}}),"undefined"!=typeof Symbol&&"undefined"!=typeof Symbol.iterator&&(r[c][Symbol.iterator]=r[c].__iter__),e=f.Permutation=g(r,{constructor:function vn(n,t){var e=this;return e instanceof vn?void r.call(e,[n,"[object Array]"===m.call(t)?t:!1]):new vn(n,t)},__static__:{C:function(n,t){return X(n,t[0])},P:r.P,T:r.T,G:function(n,t){return q(n,t[0])},count:function(n){if(n[1]){for(var t=[n[0]],r=0,e=n[1].length;e>r;r++)t.push(n[1][r].length);return f.Math.Multinomial(t)}return f.Math.Factorial(n[0])},rand:function(n){n=n[0];var t,r=new Array(n);for(t=0;n>t;t++)r[t]=t;return P(r,!1,!1)},stochastic:function(n,t,r){if(t=t[0],n.length!==t||n[0].length!==t)throw new Error("Stochastic Matrix dimensions and Permutation dimensions do not match!");var e,i,u,o,l,a,c,s,_=new Array(t),h=new Array(t),d=0,m=f.Math.rnd,v=!1;for(i=0;t>i;i++)h[i]=0;if(r){if(v=!0,!r.length){for(r.N=0,e=new Array(t),i=0;t>i;i++)e[i]=0;for(i=0;t>i;i++)r.push(e.slice())}d=++r.N}for(s=!v,i=0;t>i;)for(o=m(),c=0,l=n[i],v&&(a=r[i]),u=0;t>u;u++){if(o>c&&o<=c+l[u]){0===h[u]&&(s||i+1===t||a[u]+1<=(d+1)*l[u])&&(h[u]=1,_[i]=u,v&&a[u]++,i++);break}c+=l[u]}return _},rank:function(n,t){t=t[0];var r,e,i,u,o=f.Arithmetic,l=o.N,a=o.O,c=o.I,s=a,_=f.Math.ceil(p(t)),h=(1<<1+_)-1,d=new Array(h),m=o.shl(c,_);for(r=0;h>r;r++)d[r]=a;for(r=0;t>r;r++){for(u=l(n[r]),i=o.val(o.add(m,u)),e=0;_>e;e++)1&i&&(u=o.sub(u,d[i>>>1<<1])),d[i]=o.add(d[i],1),i>>>=1;d[i]=o.add(d[i],1),s=o.add(o.mul(s,l(t-r)),u)}return s},unrank:function(n,t,r){var e,i,u,o,l,a,c,s,_,h,d,m,v=f.Arithmetic,A=this,g=v.N,x=v.O,y=v.I;for(r=null!=r?r:A.count(t),t=t[0],e=new Array(t),i=v.div(r,t),_=f.Math.ceil(p(t)),h=(1<<1+_)-1,d=new Array(h),m=v.shl(y,_),u=0;_>=u;u++)for(o=1,l=1<=o;o++)d[l-1+o]=v.shl(y,_-u);for(s=t-1,u=0;t>u;u++){for(a=v.div(n,i),c=1,o=0;_>o;o++)d[c]=v.sub(d[c],1),c<<=1,v.gte(a,d[c])&&(a=v.sub(a,d[c]),c++);d[c]=x,e[u]=v.val(v.sub(g(c),m)),s&&(n=v.mod(n,i),i=v.div(i,s),s--)}return e},shuffle:function(n,t){return P(n,!0===t,!1)},inverse:function(n){var t,r=n.length,e=new Array(r);for(t=0;r>t;t++)e[n[t]]=t;return e},product:function(){var n,t,r,e=arguments,i=e.length,u=i?e[0]:[],o=u.length;for(t=1;i>t;t++)for(r=u.slice(),n=0;o>n;n++)u[n]=r[e[t][n]];return u},permute:function(n,t,r){var e,i,u,o=n.length;for(!0===r?(i=new Array(o),u=n):(i=n,u=n.slice()),e=0;o>e;e++)i[e]=u[t[e]];return i},toCycles:function(n,t){var r,e,i,u=n.length,o=[],l=!0===t?1:0,a=new Array(u),f=new Array(u);for(r=0;u>r;r++)f[r]=r,a[r]=0;for(i=[e=f.shift()],a[e]=1;f.length;){if(e=n[e],a[e])for(i.length>l&&o.push(i),i=[];f.length&&a[e=f.shift()];);a[e]||(i.push(e),a[e]=1)}return i.length>l&&o.push(i),o},fromCycles:function(n,t){var r,e,i,u,o=new Array(t),l=n.length;for(e=0;t>e;e++)o[e]=e;for(r=0;l>r;r++)if(u=n[r],i=u.length,!(2>i)){for(e=0;i-1>e;e++)o[u[e]]=u[e+1];o[u[i-1]]=u[0]}return o},toSwaps:function(n){var t,r,i,u=(n.length,[]),o=e.toCycles(n,!0);for(t=0,r=o.length;r>t;t++)i=o[t],u=u.concat(U(i));return u},fromSwaps:function(n,t){var r,e,i,u=n.length,o=new Array(t);for(r=0;t>r;r++)o[r]=r;for(r=0;u>r;r++)e=n[r],i=o[e[0]],o[e[0]]=o[e[1]],o[e[1]]=i;return o},toMatrix:function(n,t){var r,e,i=n.length,u=new Array(i);for(t=!0===t,r=0;i>r;r++)for(u[r]=new Array(i),e=0;i>e;e++)u[r][e]=0;for(r=0;i>r;r++)t?u[n[r]][r]=1:u[r][n[r]]=1;return u},fromMatrix:function(n,t){var r,e,i=n.length,u=new Array(i);for(t=!0===t,r=0;i>r;r++)for(e=0;i>e;e++)n[r][e]&&(t?u[e]=r:u[r]=e);return u}},item0:function(n,t){var r,e=this,i=e[s],u=e.n,o=u[0],l=new Array(o);for(r=0;o>r;r++)l[r]=r;return-1===n?i.C(l,u):l},succ:function(n,t,r,e){if(t){var i,u,o,l,a,f=this,c=f.n[0],s=t.slice();if(-1===n){for(i=c-2;i>=0&&t[i]<=t[i+1];)i--;if(i>=0){for(u=c-1;u>i&&t[i]<=t[u];)u--;for(a=s[i],s[i]=s[u],s[u]=a,o=i+1,l=c-1;l>o;)a=s[o],s[o++]=s[l],s[l--]=a}else s=null}else{for(i=c-2;i>=0&&t[i]>=t[i+1];)i--;if(i>=0){for(u=c-1;u>i&&t[i]>=t[u];)u--;for(a=s[i],s[i]=s[u],s[u]=a,o=i+1,l=c-1;l>o;)a=s[o],s[o++]=s[l],s[l--]=a}else s=null}return s}return null}}),i=f.Combination=g(r,{constructor:function An(n,t,e){var i=this;return i instanceof An?void r.call(i,[n,t,"repeated"===String(e).toLowerCase()]):new An(n,t,e)},__static__:{C:function(n,t){return X(n,t[0])},P:r.P,T:r.T,G:function(n,t){return q(n,t[0])},count:function(n){return f.Math.Binomial(n[2]?n[0]+n[1]-1:n[0],n[1])},rand:function(n){var t,r,e,i,u,o=f.Math.rndInt,l=n[2];if(e=n[1],n=n[0],i=n-e,u=n-1,l)if(1===e)t=[o(0,u)];else for(t=[],r=0;e>r;r++)R(t,o(0,u));else{var a,c,s;if(1===e)t=[o(0,u)];else if(n===e)for(t=new Array(e),r=0;e>r;r++)t[r]=r;else if(e>i){for(a={},s=[],r=0;i>r;r++){for(c=o(0,u);1===a[c];)c=o(0,u);a[c]=1,R(s,c)}t=V(s,n)}else for(a={},t=[],r=0;e>r;r++){for(c=o(0,u);1===a[c];)c=o(0,u);a[c]=1,R(t,c)}}return t},stochastic:r.stochastic,rank:function(n,t,r){var e,i,u,o,l,a,c=f.Arithmetic,s=c.add,_=c.sub,h=c.O,d=t[2],m=f.Math.Binomial;for(o=t[1],t=t[0],l=d?t+o-1:t,a=r?r:m(l,o),e=1;o>=e;e++)i=l-1-n[e-1],u=o+1-e,i>=u&&(h=s(h,m(i,u)));return _(_(a,1),h)},unrank:function(n,t,r){var e,i,u,o,l,a,c,s=f.Arithmetic,_=s.N,h=s.O,d=this,m=t[2];r=null!=r?r:d.count(t),u=t[1],t=t[0],o=m?t+u-1:t,e=new Array(u),i=r,n=s.sub(s.sub(i,1),n),i=s.div(s.mul(i,_(o-u)),o),a=o-u+1,l=u,c=o-1;do s.lte(i,n)?(e[u-l]=o-a-l+1,s.gt(i,h)&&(n=s.sub(n,i),i=s.div(s.mul(i,l),c)),l--,c--):(i=s.div(s.mul(i,_(c-l)),c),a--,c--);while(l>0);return e},complement:function(n,t){return V(n,t)},pick:function(n,t,r,e){return S(n,t,!1===r,!0===e,!0)},choose:function(n,t){var r,e=t.length,i=new Array(e);for(r=0;e>r;r++)i[r]=n[t[r]];return i},toMatrix:function(n,t,r){var e,i,u,o;for(i=t[1],t=t[0],e=new Array(t),r=!0===r,u=0;t>u;u++)for(e[u]=new Array(t),o=0;t>o;o++)e[u][o]=0;for(u=0;i>u;u++)r?e[n[u]][u]=1:e[u][n[u]]=1;return e},fromMatrix:function(n,t,r){var e,i,u,o;for(i=t[1],t=t[0],e=new Array(i),r=!0===r,u=0;t>u;u++)for(o=0;t>o;o++)n[u][o]&&(r&&i>o?e[o]=u:!r&&i>u&&(e[u]=o));return e}},item0:function(n,t){var r,e=this,i=e[s],u=e.n,o=u[2],l=u[1],a=new Array(l);if(o)for(r=0;l>r;r++)a[r]=0;else for(r=0;l>r;r++)a[r]=r;return-1===n?i.C(a,u):a},succ:function(n,t,r,e){if(t){var i,u,r,o,l,a=this,f=a.n,c=f[2],s=c?0:1,_=t.slice();if(i=f[1],f=f[0],-1===n){for(u=i-1,r=-1;u>0;){if(_[u]>_[u-1]+s){r=u;break}u--}if(-1===r&&0<_[0]&&(r=0),r>-1){for(l=f-1+s,u=i-1;u>r;u--)l-=s,_[u]=l;_[r]--}else _=null}else{if(u=i-1,r=-1,c)for(;u>=0;){if(_[u]=0;){if(_[u]-1)for(l=_[r]+1-s,u=r;i>u;u++)l+=s,_[u]=l;else _=null}return _}return null}}),i.conjugate=i.complement,o=f.Powerset=f.Subset=g(r,{constructor:function gn(n){var t=this;return t instanceof gn?void r.call(t,n):new gn(n)},__static__:{C:r.C,P:r.P,T:r.T,G:r.G,count:function(n){return f.Math.Pow2(n)},rand:r.rand,stochastic:r.stochastic,rank:function(n,t,r){for(var e=f.Arithmetic,i=e.O,u=e.I,o=i,l=0,a=n.length;a>l;)o=e.add(o,e.shl(u,n[l++]));return o},unrank:function(n,t,r){var e=this,i=f.Arithmetic,u=[],o=0;if(i.lt(n,0)||i.gte(n,null!=r?r:e.count(t)))return null;for(;i.gt(n,0);)i.gt(i.band(n,1),0)&&u.push(o),i.gt(i.band(n,2),0)&&u.push(o+1),i.gt(i.band(n,4),0)&&u.push(o+2),i.gt(i.band(n,8),0)&&u.push(o+3),i.gt(i.band(n,16),0)&&u.push(o+4),i.gt(i.band(n,32),0)&&u.push(o+5),i.gt(i.band(n,64),0)&&u.push(o+6),i.gt(i.band(n,128),0)&&u.push(o+7),o+=8,n=i.shr(n,8);return u}},dual:function(n,t,r){if(null==n)return null;r=r||0;var e=this,i=e[s],u=(i.C,i.P),o=(i.T,i.G),l=e._count,a=e.n,f=rn&r;return cn&r?f?u(n,a):n:on&r?f?u(i.unrank(o(t),a,l),a):i.unrank(o(t),a,l):f?u(n,a):G(n)},item0:function(n,t){var r=this.n,e=(on|un)&(t||0);if(-1===n){if(e)return[];var i,u=new Array(r);for(i=0;r>i;i++)u[i]=i;return u}if(e){var i,u=new Array(r);for(i=0;r>i;i++)u[i]=i;return u}return[]},succ:function(n,t,e,i){return-1!==n&&(n=1),(on|un)&(i||0)&&(n=-n),null==t?null:r[c].succ.call(this,n,t,e,i)}}),u=f.Partition=g(r,{constructor:function pn(n,t){var e=this;return e instanceof pn?void r.call(e,[n,"set"===String(t).toLowerCase()]):new pn(n,t)},__static__:{C:function(n,t){return F(n)},P:r.P,T:r.T,G:function(n,t){return q(n,t[0])},count:function(n){n=n[0];var t,r,e=f.Math.Partitions,i=f.Arithmetic.add,u=f.Arithmetic.N(n>1?2:1);for(t=2;n>t;t++)for(r=n-t+1;r>=1;r--)u=i(u,e(n,t,r));return u},rand:function(n,t){return null},stochastic:r.stochastic,rank:function(n,t,r,e,i,u){return f.Arithmetic.O},unrank:function(n,t,r){return null},toSet:function(n){return n?H(n):null},toNumeric:function(n){return n?B(n):null},conjugate:function(n){return F(n)},pack:function(n){var t,r=[],e=n.length,i=n[0],u=[i,1];for(t=1;e>t;t++)i===n[t]?u[1]++:(r.push(u),i=n[t],u=[i,1]);return r.push(u),r},unpack:function(n){var t,r,e,i,u,o=[],l=n.length;for(t=0;l>t;t++)if(u=n[t],1===u[1])o.push(u[0]);else for(e=u[1],i=u[0],r=0;e>r;r++)o.push(i);return o}},dual:function(n,t,r){if(null==n)return null;r=r||0;var e=this,i=e[s],u=e.n;return u[1]?i.toSet(n):cn&r?n:G(n)},item0:function(n,t){var r,e=this,i=e[s],u=e.n[0],o=new Array(u);for(r=0;r1){for(u=_.length,i=u-1;i>=0&&1===_[i];)i--;for(o=_[i]-1,_=_.slice(0,i+1),_[i]=o,a=Y(_),f=s-a;f>0;)l=f,l>o?(l=o,_.push(l)):_.push(f),f-=l}else _=null;else if(_[0]0&&i--;i>0&&_[i]===_[i-1];)i--;for(_[i]++,_=_.slice(0,i+1),a=Y(_),f=s-a;f>0;)_.push(1),f--}else _=null;return _}return null}}),u.transpose=u.conjugate,l=f.Tensor=g(r,{constructor:function xn(){var n=this,t=arguments;return n instanceof xn?void(t.length?r.call(n,t[0]instanceof Array?t[0]:d.call(t)):(n.n=[],n._count=0)):(n=new xn,t.length?r.call(n,t[0]instanceof Array?t[0]:d.call(t)):(n.n=[],n._count=0),n)},__static__:{C:r.C,P:r.P,T:r.T,G:r.G,count:function(n){return n&&n.length?z(n):0},rand:function(n){var t,r=f.Math.rndInt,e=n,i=e.length,u=new Array(i);for(t=0;i>t;t++)u[t]=r(0,e[t]-1);return u},stochastic:r.stochastic,rank:function(n,t){var r,e,i=f.Arithmetic,u=t,o=u.length;if(!o)return-1;for(r=i.O,e=0;o>e;e++)r=i.add(i.mul(r,u[e]),n[e]);return r},unrank:function(n,t){var r,e,i,u,o,l=f.Arithmetic,a=t,c=a.length;if(!c)return[];for(o=new Array(c),r=n,i=c-1;i>=0;i--)e=a[i],u=l.mod(r,e),r=l.div(r,e),o[i]=l.val(u);return o},product:C,component:function(n,t){var r,e,i,u,o,l,a=[],f=t,c=f.length;for(r=0;c>r;r++)if(i=f[r],o=n[r],u=i[o],u instanceof Array)for(e=0,l=u.length;l>e;e++)a.push(u[e]);else a.push(u);return a}},item0:function(n,t){var r,e=this,i=e[s],u=e.n,o=u.length,l=new Array(o);for(r=0;o>r;r++)l[r]=0;return-1===n?i.C(l,u):l},succ:function(n,t,r,e){if(t){var i,u,o=this,l=o.n,a=t.slice(),f=l,c=f.length;if(-1===n){for(i=c-1;i>=0&&a[i]-1<0;)i--;if(i>=0)for(a[i]--,u=i+1;c>u;u++)a[u]=f[u]-1;else a=null}else{for(i=c-1;i>=0&&a[i]+1===f[i];)i--;if(i>=0)for(a[i]++,u=i+1;c>u;u++)a[u]=0;else a=null}return a}return null}}),a=f.Tuple=g(r,{constructor:function yn(n,t){var e=this;return e instanceof yn?void r.call(e,[n||1,t||2]):new yn(n,t)},__static__:{C:function(n,t){return X(n,t[1])},P:r.P,T:r.T,G:function(n,t){return q(n,t[1])},count:function(n){return f.Math.Exp(n[1],n[0])},rand:function(n){var t,r=f.Math.rndInt,e=n[0],i=new Array(e);for(n=n[1]-1,t=0;e>t;t++)i[t]=r(0,n);return i},stochastic:l.stochastic,rank:function(n,t){var r,e,i=f.Arithmetic,u=t[0];for(t=t[1],r=i.O,e=0;u>e;e++)r=i.add(i.mul(r,t),n[e]);return r},unrank:function(n,t){var r,e,i,u,o,l=f.Arithmetic,a=t[0];for(t=t[1],o=new Array(a),r=n,i=a-1;i>=0;i--)e=t,u=l.mod(r,e),r=l.div(r,e),o[i]=l.val(u);return o}},item0:function(n,t){var r,e=this,i=e[s],u=e.n,o=u[0],l=new Array(o);for(r=0;o>r;r++)l[r]=0;return-1===n?i.C(l,u):l},succ:function(n,t,r,e){if(t){var i,u,o=this,l=o.n,a=t.slice(),f=l[0],l=l[1];if(-1===n){for(i=f-1;i>=0&&a[i]-1<0;)i--;if(i>=0)for(a[i]--,u=i+1;f>u;u++)a[u]=l-1;else a=null}else{for(i=f-1;i>=0&&a[i]+1===l;)i--;if(i>=0)for(a[i]++,u=i+1;f>u;u++)a[u]=0;else a=null}return a}return null}}),f}); \ No newline at end of file diff --git a/test/biginteger/arithmetic.js b/test/biginteger/arithmetic.js index 3fb2994..27b5a87 100644 --- a/test/biginteger/arithmetic.js +++ b/test/biginteger/arithmetic.js @@ -3,30 +3,41 @@ function use_biginteger_arithmetic( Abacus ) { // plug-in bigInteger arithmetic routines - var bigInt = require( './BigInteger.js' ); - Abacus.Arithmetic.equ = function(a, b){ return bigInt(a).eq(bigInt(b)); }; - Abacus.Arithmetic.gte = function(a, b){ return bigInt(a).geq(bigInt(b)); }; - Abacus.Arithmetic.lte = function(a, b){ return bigInt(a).leq(bigInt(b)); }; - Abacus.Arithmetic.gt = function(a, b){ return bigInt(a).gt(bigInt(b)); }; - Abacus.Arithmetic.lt = function(a, b){ return bigInt(a).lt(bigInt(b)); }; + var Arithmetic = Abacus.Arithmetic, bigInt = require( './BigInteger.js' ); - Abacus.Arithmetic.add = function(a, b){ return bigInt(a).plus(bigInt(b)); }; - Abacus.Arithmetic.sub = function(a, b){ return bigInt(a).minus(bigInt(b)); }; - Abacus.Arithmetic.mul = function(a, b){ return bigInt(a).times(bigInt(b)); }; - Abacus.Arithmetic.div = function(a, b){ return bigInt(a).over(bigInt(b)); }; - Abacus.Arithmetic.mod = function(a, b){ return bigInt(a).mod(bigInt(b)); }; - Abacus.Arithmetic.pow = function(a, b){ return bigInt(a).pow(bigInt(b)); }; + Arithmetic.O = bigInt.zero; + Arithmetic.I = bigInt.one; - Abacus.Arithmetic.shl = function(a, b){ return bigInt(a).shiftLeft(bigInt(b)); }; - Abacus.Arithmetic.shr = function(a, b){ return bigInt(a).shiftRight(bigInt(b)); }; - Abacus.Arithmetic.bor = function(a, b){ return bigInt(a).or(bigInt(b)); }; - Abacus.Arithmetic.band = function(a, b){ return bigInt(a).and(bigInt(b)); }; + Arithmetic.equ = function( a, b ){ return a.eq( b ); }; + Arithmetic.gte = function( a, b ){ return a.geq( b ); }; + Arithmetic.lte = function( a, b ){ return a.leq( b ); }; + Arithmetic.gt = function( a, b ){ return a.gt( b ); }; + Arithmetic.lt = function( a, b ){ return a.lt( b ); }; - Abacus.Arithmetic.rnd = bigInt.randBetween; - Abacus.Arithmetic.min = bigInt.min; - Abacus.Arithmetic.max = bigInt.max; + Arithmetic.inside = function( a, m, M, closed ){ return closed ? (a.geq( m )) && (a.leq( M )) : (a.gt( m )) && (a.lt( M )); + }; + Arithmetic.clamp = function( a, m, M ){ return a.lt( m ) ? m : (a.gt( M ) ? M : a); }; + Arithmetic.wrap = function( a, m, M ){ return a.lt( m ) ? M : (a.gt( M ) ? m : a); }; + Arithmetic.wrapR = function( a, M ){ return a.lt( 0 ) ? a.plus( M ) : a; }; - Abacus.Arithmetic.num = function(a){ return bigInt(a); }; + Arithmetic.add = function( a, b ){ return a.plus( b ); }; + Arithmetic.sub = function( a, b ){ return a.minus( b ); }; + Arithmetic.mul = function( a, b ){ return a.times( b ); }; + Arithmetic.div = function( a, b ){ return a.over( b ); }; + Arithmetic.mod = function( a, b ){ return a.mod( b ); }; + Arithmetic.pow = function( a, b ){ return a.pow( b ); }; + + Arithmetic.shl = function( a, b ){ return a.shiftLeft( b ); }; + Arithmetic.shr = function( a, b ){ return a.shiftRight( b ); }; + Arithmetic.bor = function( a, b ){ return a.or( b ); }; + Arithmetic.band = function( a, b ){ return a.and( b ); }; + Arithmetic.xor = function( a, b ){ return a.xor( b ); }; + + Arithmetic.rnd = bigInt.randBetween; + Arithmetic.min = bigInt.min; + Arithmetic.max = bigInt.max; + + Arithmetic.num = function( a ){ return bigInt( a ); }; } module.exports = use_biginteger_arithmetic; \ No newline at end of file diff --git a/test/combinations.js b/test/combinations.js index 1b7f48e..2e93c06 100644 --- a/test/combinations.js +++ b/test/combinations.js @@ -1,6 +1,16 @@ var isNode = 'undefined' !== typeof global && '[object global]' === {}.toString.call(global); var Abacus = isNode ? require('../src/js/Abacus.js') : window.Abacus, echo = console.log; +function print_all( o, prev ) +{ + if ( -1 === prev ) + while ( o.hasPrev() ) echo( o.prev() ); + else + //while ( o.hasNext() ) echo( o.next() ); + // iterator/iterable are supported + for(let item of o) echo( item ); +} + // Note: Due to the large number of combinatorial samples, // Abacus combinatorics use an Iterator pattern to succesively and consistently // generate all combinatorial objects without storing all of them in memory at once @@ -16,8 +26,6 @@ o = Abacus.Combination(6,3); echo('o.total()'); echo(o.total()); -echo('default order is "lex", lexicographic-order'); - echo('o.next()'); echo(o.next()); @@ -26,37 +34,40 @@ echo(o.hasNext()); echo('o.next()'); echo(o.next()); - +echo('default order is "lex", lexicographic-order'); echo('o.rewind()'); -o.rewind(); -while (o.hasNext()) echo (o.next()); +print_all( o.rewind() ); +echo('backwards'); echo('o.forward()'); -o.forward(); -while (o.hasPrev()) echo (o.prev()); +print_all( o.forward(), -1 ); + +echo('o.order("lex,reflected")'); +print_all( o.order("lex,reflected") ); -echo('o.order("revlex")'); -o.order("revlex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("lex,reversed")'); +print_all( o.order("lex,reversed") ); echo('o.order("colex")'); -o.order("colex"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("colex") ); -echo('o.order("revcolex")'); -o.order("revcolex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("colex,reflected")'); +print_all( o.order("colex,reflected") ); +echo('o.order("colex,reversed")'); +print_all( o.order("colex,reversed") ); -echo('o.random()'); -echo(o.random()); +echo('o.order("gray")'); +//print_all( o.order("gray") ); echo('o.order("random")'); -o.order("random"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("random") ); + +echo('o.random()'); +echo(o.random()); echo('o.order("colex").range(-5, -1)'); -echo (o.order("colex").range(-5, -1)); +print_all(o.order("colex").range(-5, -1)); // dispose diff --git a/test/combinations.txt b/test/combinations.txt index 85d6782..1951afa 100644 --- a/test/combinations.txt +++ b/test/combinations.txt @@ -3,13 +3,13 @@ Abacus.Combinations (VERSION = 0.1.0) o = Abacus.Combination(6,3) o.total() 20 -default order is "lex", lexicographic-order o.next() [ 0, 1, 2 ] o.hasNext() true o.next() [ 0, 1, 3 ] +default order is "lex", lexicographic-order o.rewind() [ 0, 1, 2 ] [ 0, 1, 3 ] @@ -31,7 +31,10 @@ o.rewind() [ 2, 3, 5 ] [ 2, 4, 5 ] [ 3, 4, 5 ] +backwards o.forward() +[ 5, 4, 3 ] +[ 4, 4, 5 ] [ 3, 4, 5 ] [ 2, 4, 5 ] [ 2, 3, 5 ] @@ -52,7 +55,30 @@ o.forward() [ 0, 1, 4 ] [ 0, 1, 3 ] [ 0, 1, 2 ] -o.order("revlex") +o.order("lex,reflected") +[ 2, 1, 0 ] +[ 3, 1, 0 ] +[ 4, 1, 0 ] +[ 5, 1, 0 ] +[ 3, 2, 0 ] +[ 4, 2, 0 ] +[ 5, 2, 0 ] +[ 4, 3, 0 ] +[ 5, 3, 0 ] +[ 5, 4, 0 ] +[ 3, 2, 1 ] +[ 4, 2, 1 ] +[ 5, 2, 1 ] +[ 4, 3, 1 ] +[ 5, 3, 1 ] +[ 5, 4, 1 ] +[ 4, 3, 2 ] +[ 5, 3, 2 ] +[ 5, 4, 2 ] +[ 5, 4, 3 ] +o.order("lex,reversed") +[ 5, 4, 3 ] +[ 4, 4, 5 ] [ 3, 4, 5 ] [ 2, 4, 5 ] [ 2, 3, 5 ] @@ -74,6 +100,8 @@ o.order("revlex") [ 0, 1, 3 ] [ 0, 1, 2 ] o.order("colex") +[ 2, 1, 0 ] +[ 0, 1, 1 ] [ 0, 1, 2 ] [ 0, 1, 3 ] [ 0, 2, 3 ] @@ -94,7 +122,30 @@ o.order("colex") [ 1, 4, 5 ] [ 2, 4, 5 ] [ 3, 4, 5 ] -o.order("revcolex") +o.order("colex,reflected") +[ 0, 1, 2 ] +[ 1, 1, 0 ] +[ 2, 1, 0 ] +[ 3, 1, 0 ] +[ 3, 2, 0 ] +[ 3, 2, 1 ] +[ 4, 1, 0 ] +[ 4, 2, 0 ] +[ 4, 2, 1 ] +[ 4, 3, 0 ] +[ 4, 3, 1 ] +[ 4, 3, 2 ] +[ 5, 1, 0 ] +[ 5, 2, 0 ] +[ 5, 2, 1 ] +[ 5, 3, 0 ] +[ 5, 3, 1 ] +[ 5, 3, 2 ] +[ 5, 4, 0 ] +[ 5, 4, 1 ] +[ 5, 4, 2 ] +[ 5, 4, 3 ] +o.order("colex,reversed") [ 3, 4, 5 ] [ 2, 4, 5 ] [ 1, 4, 5 ] @@ -115,29 +166,34 @@ o.order("revcolex") [ 0, 2, 3 ] [ 0, 1, 3 ] [ 0, 1, 2 ] -o.random() -[ 2, 3, 5 ] +o.order("gray") o.order("random") -[ 0, 3, 4 ] -[ 1, 4, 5 ] -[ 0, 1, 5 ] -[ 1, 2, 4 ] +[ 0, 1, 4 ] +[ 1, 2, 3 ] +[ 0, 1, 3 ] [ 0, 3, 5 ] +[ 2, 4, 5 ] +[ 2, 3, 5 ] +[ 0, 1, 5 ] +[ 0, 1, 2 ] +[ 2, 3, 4 ] +[ 0, 4, 5 ] +[ 0, 3, 4 ] [ 0, 2, 3 ] -[ 1, 2, 5 ] +[ 3, 4, 5 ] [ 0, 2, 5 ] [ 0, 2, 4 ] +[ 1, 2, 4 ] +[ 1, 4, 5 ] +[ 1, 3, 5 ] [ 1, 3, 4 ] +[ 1, 2, 5 ] +o.random() [ 2, 3, 4 ] -[ 2, 4, 5 ] -[ 0, 1, 4 ] -[ 0, 4, 5 ] -[ 1, 2, 3 ] -[ 1, 3, 5 ] +o.order("colex").range(-5, -1) [ 2, 3, 5 ] +[ 0, 4, 5 ] +[ 1, 4, 5 ] +[ 2, 4, 5 ] [ 3, 4, 5 ] -[ 0, 1, 3 ] -[ 0, 1, 2 ] -o.order("colex").range(-5, -1) -[ [ 2, 3, 5 ], [ 0, 4, 5 ], [ 1, 4, 5 ], [ 2, 4, 5 ], [ 3, 4, 5 ] ] o.dispose() diff --git a/test/combinations_repeats.js b/test/combinations_repeats.js index 06aafe4..7adb496 100644 --- a/test/combinations_repeats.js +++ b/test/combinations_repeats.js @@ -1,6 +1,16 @@ var isNode = 'undefined' !== typeof global && '[object global]' === {}.toString.call(global); var Abacus = isNode ? require('../src/js/Abacus.js') : window.Abacus, echo = console.log; +function print_all( o, prev ) +{ + if ( -1 === prev ) + while ( o.hasPrev() ) echo( o.prev() ); + else + //while ( o.hasNext() ) echo( o.next() ); + // iterator/iterable are supported + for(let item of o) echo( item ); +} + // Note: Due to the large number of combinatorial samples, // Abacus combinatorics use an Iterator pattern to succesively and consistently // generate all combinatorial objects without storing all of them in memory at once @@ -10,14 +20,12 @@ echo('Abacus.CombinationRepeats (VERSION = '+Abacus.VERSION+')'); echo('---'); // CombinationRepeats -echo('o = Abacus.CombinationRepeat(6,3)'); -o = Abacus.CombinationRepeat(6,3); +echo('o = Abacus.Combination(6,3,"repeated")'); +o = Abacus.Combination(6,3,"repeated"); echo('o.total()'); echo(o.total()); -echo('default order is "lex", lexicographic-order'); - echo('o.next()'); echo(o.next()); @@ -26,37 +34,41 @@ echo(o.hasNext()); echo('o.next()'); echo(o.next()); - +echo('default order is "lex", lexicographic-order'); echo('o.rewind()'); -o.rewind(); -while (o.hasNext()) echo (o.next()); +print_all( o.rewind() ); +echo('backwards'); echo('o.forward()'); -o.forward(); -while (o.hasPrev()) echo (o.prev()); +print_all( o.forward(), -1 ); -echo('o.order("revlex")'); -o.order("revlex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("lex,reflected")'); +print_all( o.order("lex,reflected") ); + +echo('o.order("lex,reversed")'); +print_all( o.order("lex,reversed") ); echo('o.order("colex")'); -o.order("colex"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("colex") ); + +echo('o.order("colex,reflected")'); +print_all( o.order("colex,reflected") ); -echo('o.order("revcolex")'); -o.order("revcolex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("colex,reversed")'); +print_all( o.order("colex,reversed") ); +echo('o.order("gray")'); +//print_all( o.order("gray") ); + +echo('o.order("random")'); +print_all( o.order("random") ); echo('o.random()'); echo(o.random()); -echo('o.order("random")'); -o.order("random"); -while (o.hasNext()) echo (o.next()); echo('o.order("colex").range(-5, -1)'); -echo (o.order("colex").range(-5, -1)); +print_all(o.order("colex").range(-5, -1)); // dispose diff --git a/test/combinations_repeats.txt b/test/combinations_repeats.txt index bc7569a..ccf4ec6 100644 --- a/test/combinations_repeats.txt +++ b/test/combinations_repeats.txt @@ -1,15 +1,15 @@ Abacus.CombinationRepeats (VERSION = 0.1.0) --- -o = Abacus.CombinationRepeat(6,3) +o = Abacus.Combination(6,3,"repeated") o.total() 56 -default order is "lex", lexicographic-order o.next() [ 0, 0, 0 ] o.hasNext() true o.next() [ 0, 0, 1 ] +default order is "lex", lexicographic-order o.rewind() [ 0, 0, 0 ] [ 0, 0, 1 ] @@ -67,6 +67,7 @@ o.rewind() [ 4, 4, 5 ] [ 4, 5, 5 ] [ 5, 5, 5 ] +backwards o.forward() [ 5, 5, 5 ] [ 4, 5, 5 ] @@ -124,7 +125,64 @@ o.forward() [ 0, 0, 2 ] [ 0, 0, 1 ] [ 0, 0, 0 ] -o.order("revlex") +o.order("lex,reflected") +[ 0, 0, 0 ] +[ 1, 0, 0 ] +[ 2, 0, 0 ] +[ 3, 0, 0 ] +[ 4, 0, 0 ] +[ 5, 0, 0 ] +[ 1, 1, 0 ] +[ 2, 1, 0 ] +[ 3, 1, 0 ] +[ 4, 1, 0 ] +[ 5, 1, 0 ] +[ 2, 2, 0 ] +[ 3, 2, 0 ] +[ 4, 2, 0 ] +[ 5, 2, 0 ] +[ 3, 3, 0 ] +[ 4, 3, 0 ] +[ 5, 3, 0 ] +[ 4, 4, 0 ] +[ 5, 4, 0 ] +[ 5, 5, 0 ] +[ 1, 1, 1 ] +[ 2, 1, 1 ] +[ 3, 1, 1 ] +[ 4, 1, 1 ] +[ 5, 1, 1 ] +[ 2, 2, 1 ] +[ 3, 2, 1 ] +[ 4, 2, 1 ] +[ 5, 2, 1 ] +[ 3, 3, 1 ] +[ 4, 3, 1 ] +[ 5, 3, 1 ] +[ 4, 4, 1 ] +[ 5, 4, 1 ] +[ 5, 5, 1 ] +[ 2, 2, 2 ] +[ 3, 2, 2 ] +[ 4, 2, 2 ] +[ 5, 2, 2 ] +[ 3, 3, 2 ] +[ 4, 3, 2 ] +[ 5, 3, 2 ] +[ 4, 4, 2 ] +[ 5, 4, 2 ] +[ 5, 5, 2 ] +[ 3, 3, 3 ] +[ 4, 3, 3 ] +[ 5, 3, 3 ] +[ 4, 4, 3 ] +[ 5, 4, 3 ] +[ 5, 5, 3 ] +[ 4, 4, 4 ] +[ 5, 4, 4 ] +[ 5, 5, 4 ] +[ 5, 5, 5 ] +o.order("lex,reversed") [ 5, 5, 5 ] [ 4, 5, 5 ] [ 4, 4, 5 ] @@ -238,7 +296,64 @@ o.order("colex") [ 3, 5, 5 ] [ 4, 5, 5 ] [ 5, 5, 5 ] -o.order("revcolex") +o.order("colex,reflected") +[ 0, 0, 0 ] +[ 1, 0, 0 ] +[ 1, 1, 0 ] +[ 1, 1, 1 ] +[ 2, 0, 0 ] +[ 2, 1, 0 ] +[ 2, 1, 1 ] +[ 2, 2, 0 ] +[ 2, 2, 1 ] +[ 2, 2, 2 ] +[ 3, 0, 0 ] +[ 3, 1, 0 ] +[ 3, 1, 1 ] +[ 3, 2, 0 ] +[ 3, 2, 1 ] +[ 3, 2, 2 ] +[ 3, 3, 0 ] +[ 3, 3, 1 ] +[ 3, 3, 2 ] +[ 3, 3, 3 ] +[ 4, 0, 0 ] +[ 4, 1, 0 ] +[ 4, 1, 1 ] +[ 4, 2, 0 ] +[ 4, 2, 1 ] +[ 4, 2, 2 ] +[ 4, 3, 0 ] +[ 4, 3, 1 ] +[ 4, 3, 2 ] +[ 4, 3, 3 ] +[ 4, 4, 0 ] +[ 4, 4, 1 ] +[ 4, 4, 2 ] +[ 4, 4, 3 ] +[ 4, 4, 4 ] +[ 5, 0, 0 ] +[ 5, 1, 0 ] +[ 5, 1, 1 ] +[ 5, 2, 0 ] +[ 5, 2, 1 ] +[ 5, 2, 2 ] +[ 5, 3, 0 ] +[ 5, 3, 1 ] +[ 5, 3, 2 ] +[ 5, 3, 3 ] +[ 5, 4, 0 ] +[ 5, 4, 1 ] +[ 5, 4, 2 ] +[ 5, 4, 3 ] +[ 5, 4, 4 ] +[ 5, 5, 0 ] +[ 5, 5, 1 ] +[ 5, 5, 2 ] +[ 5, 5, 3 ] +[ 5, 5, 4 ] +[ 5, 5, 5 ] +o.order("colex,reversed") [ 5, 5, 5 ] [ 4, 5, 5 ] [ 3, 5, 5 ] @@ -295,65 +410,70 @@ o.order("revcolex") [ 0, 1, 1 ] [ 0, 0, 1 ] [ 0, 0, 0 ] -o.random() -[ 4, 4, 5 ] +o.order("gray") o.order("random") -[ 1, 5, 5 ] -[ 1, 2, 4 ] -[ 0, 3, 3 ] -[ 0, 1, 5 ] -[ 1, 2, 3 ] -[ 0, 5, 5 ] -[ 0, 3, 4 ] -[ 1, 2, 2 ] -[ 1, 4, 5 ] -[ 1, 4, 4 ] -[ 0, 0, 4 ] -[ 1, 1, 1 ] -[ 2, 4, 4 ] -[ 2, 3, 5 ] -[ 3, 3, 4 ] -[ 2, 4, 5 ] +[ 4, 6, 7 ] [ 0, 3, 5 ] -[ 0, 4, 4 ] +[ 3, 5, 6 ] +[ 1, 4, 6 ] +[ 0, 1, 7 ] +[ 4, 5, 6 ] +[ 1, 5, 7 ] +[ 0, 1, 5 ] +[ 0, 1, 6 ] +[ 1, 4, 7 ] +[ 1, 5, 6 ] +[ 0, 3, 6 ] +[ 1, 6, 7 ] +[ 4, 5, 7 ] +[ 0, 2, 7 ] +[ 2, 6, 7 ] [ 0, 2, 4 ] -[ 1, 3, 3 ] +[ 2, 3, 4 ] +[ 3, 4, 6 ] [ 0, 4, 5 ] -[ 3, 3, 3 ] -[ 3, 5, 5 ] +[ 2, 5, 7 ] +[ 3, 6, 7 ] +[ 1, 2, 4 ] +[ 2, 3, 5 ] +[ 3, 5, 7 ] +[ 2, 3, 7 ] +[ 3, 4, 7 ] +[ 2, 3, 6 ] [ 0, 2, 5 ] -[ 1, 3, 4 ] -[ 3, 3, 5 ] -[ 4, 4, 4 ] -[ 1, 1, 5 ] -[ 2, 2, 4 ] -[ 1, 1, 2 ] -[ 2, 5, 5 ] -[ 1, 1, 4 ] -[ 0, 2, 2 ] -[ 2, 2, 3 ] -[ 3, 4, 5 ] +[ 0, 3, 4 ] +[ 1, 4, 5 ] +[ 1, 3, 7 ] +[ 1, 3, 6 ] +[ 5, 6, 7 ] +[ 2, 4, 6 ] +[ 0, 2, 6 ] [ 1, 3, 5 ] +[ 0, 3, 7 ] [ 0, 1, 4 ] -[ 3, 4, 4 ] -[ 1, 1, 3 ] -[ 4, 5, 5 ] -[ 4, 4, 5 ] -[ 0, 1, 2 ] -[ 1, 2, 5 ] [ 0, 2, 3 ] -[ 2, 3, 4 ] -[ 2, 2, 2 ] -[ 2, 2, 5 ] [ 0, 1, 3 ] -[ 0, 0, 2 ] -[ 0, 1, 1 ] -[ 0, 0, 5 ] -[ 2, 3, 3 ] -[ 5, 5, 5 ] -[ 0, 0, 0 ] -[ 0, 0, 1 ] -[ 0, 0, 3 ] +[ 0, 6, 7 ] +[ 0, 5, 6 ] +[ 2, 5, 6 ] +[ 0, 4, 7 ] +[ 0, 1, 2 ] +[ 1, 3, 4 ] +[ 0, 4, 6 ] +[ 2, 4, 5 ] +[ 3, 4, 5 ] +[ 2, 4, 7 ] +[ 1, 2, 7 ] +[ 1, 2, 6 ] +[ 1, 2, 3 ] +[ 1, 2, 5 ] +[ 0, 5, 7 ] +o.random() +[ 0, 3, 3 ] o.order("colex").range(-5, -1) -[ [ 1, 5, 5 ], [ 2, 5, 5 ], [ 3, 5, 5 ], [ 4, 5, 5 ], [ 5, 5, 5 ] ] +[ -1, 4, 5 ] +[ 0, 4, 5 ] +[ 1, 4, 5 ] +[ 2, 4, 5 ] +[ 3, 4, 5 ] o.dispose() diff --git a/test/partitions.js b/test/partitions.js index f128bb4..a25a4fe 100644 --- a/test/partitions.js +++ b/test/partitions.js @@ -1,6 +1,16 @@ var isNode = 'undefined' !== typeof global && '[object global]' === {}.toString.call(global); var Abacus = isNode ? require('../src/js/Abacus.js') : window.Abacus, echo = console.log; +function print_all( o, prev ) +{ + if ( -1 === prev ) + while ( o.hasPrev() ) echo( o.prev() ); + else + //while ( o.hasNext() ) echo( o.next() ); + // iterator/iterable are supported + for(let item of o) echo( item ); +} + // Note: Due to the large number of combinatorial samples, // Abacus combinatorics use an Iterator pattern to succesively and consistently // generate all combinatorial objects without storing all of them in memory at once @@ -16,8 +26,6 @@ o = Abacus.Partition(5); echo('o.total()'); echo(o.total()); -echo('default order is "lex", lexicographic-order'); - echo('o.next()'); echo(o.next()); @@ -26,14 +34,13 @@ echo(o.hasNext()); echo('o.next()'); echo(o.next()); - +echo('default order is "lex", lexicographic-order'); echo('o.rewind()'); -o.rewind(); -while (o.hasNext()) echo (o.next()); +print_all( o.rewind() ); +echo('backwards'); echo('o.forward()'); -o.forward(); -while (o.hasPrev()) echo (o.prev()); +print_all( o.forward(), -1 ); // dispose echo('o.dispose()'); diff --git a/test/permutations-bigint.txt b/test/permutations-bigint.txt index a1f33de..1cfd170 100644 --- a/test/permutations-bigint.txt +++ b/test/permutations-bigint.txt @@ -4,56 +4,56 @@ o = Abacus.Permutation(50) o.total() 30414093201713378043612608166064768844377641568960512000000000000 o.random() -[ 17, - 43, - 5, - 36, +[ 31, 42, - 35, - 33, 14, - 31, - 26, + 22, + 36, + 8, + 21, + 23, + 34, + 12, + 15, + 37, + 27, 41, - 25, - 39, - 30, - 16, + 33, + 13, 10, + 46, 3, - 28, - 11, - 9, - 12, - 23, - 27, - 19, - 48, + 7, + 18, 24, - 47, - 34, - 15, + 44, + 30, 45, - 38, - 13, - 20, - 8, - 21, 32, - 44, - 18, - 7, + 35, + 16, + 4, + 48, 0, - 6, - 49, - 22, - 2, - 46, 1, - 37, - 29, + 26, + 25, + 43, 40, - 4 ] + 49, + 19, + 38, + 5, + 39, + 20, + 47, + 29, + 9, + 2, + 28, + 17, + 11, + 6 ] o.item(78043612608166064768844377641568960512000000000000,"lex") [ 0, 1, diff --git a/test/permutations.js b/test/permutations.js index 9b0ef14..8d313cd 100644 --- a/test/permutations.js +++ b/test/permutations.js @@ -1,6 +1,17 @@ var isNode = 'undefined' !== typeof global && '[object global]' === {}.toString.call(global); var Abacus = isNode ? require('../src/js/Abacus.js') : window.Abacus, echo = console.log; + +function print_all( o, prev ) +{ + if ( -1 === prev ) + while ( o.hasPrev() ) echo( o.prev() ); + else + //while ( o.hasNext() ) echo( o.next() ); + // iterator/iterable are supported + for(let item of o) echo( item ); +} + // Note: Due to the large number of combinatorial samples, // Abacus combinatorics use an Iterator pattern to succesively and consistently // generate all combinatorial objects without storing all of them in memory at once @@ -16,8 +27,6 @@ o = Abacus.Permutation(4); echo('o.total()'); echo(o.total()); -echo('default order is "lex", lexicographic-order'); - echo('o.next()'); echo(o.next()); @@ -26,41 +35,44 @@ echo(o.hasNext()); echo('o.next()'); echo(o.next()); - +echo('default order is "lex", lexicographic-order'); echo('o.rewind()'); -o.rewind(); -while (o.hasNext()) echo (o.next()); +print_all( o.rewind() ); +echo('backwards'); echo('o.forward()'); -o.forward(); -while (o.hasPrev()) echo (o.prev()); +print_all( o.forward(), -1 ); -echo('o.order("revlex")'); -o.order("revlex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("lex,reflected")'); +print_all( o.order("lex,reflected") ); + +echo('o.order("lex,reversed")'); +print_all( o.order("lex,reversed") ); echo('o.order("colex")'); -o.order("colex"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("colex") ); -echo('o.order("revcolex")'); -o.order("revcolex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("colex,reflected")'); +print_all( o.order("colex,reflected") ); +echo('o.order("colex,reversed")'); +print_all( o.order("colex,reversed") ); -echo('o.random()'); -echo(o.random()); +echo('o.order("minimal")'); +print_all( o.order("minimal") ); echo('o.order("random")'); -o.order("random"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("random") ); + +echo('o.random()'); +echo(o.random()); echo('o.order("colex").range(-5, -1)'); -echo (o.order("colex").range(-5, -1)); +print_all(o.order("colex").range(-5, -1)); echo('o.order("stochastic", [ [ 0, 1, 0, 0 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ] ]).range(0, 9)'); -echo(o.order("stochastic", [ [ 0, 1, 0, 0 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ] ]).range(0, 9)); +print_all(o.order("stochastic", [ [ 0, 1, 0, 0 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ] ]).range(0, 9)); // dispose diff --git a/test/permutations.txt b/test/permutations.txt index a7c2a3b..a25d5a5 100644 --- a/test/permutations.txt +++ b/test/permutations.txt @@ -3,13 +3,13 @@ Abacus.Permutations (VERSION = 0.1.0) o = Abacus.Permutation(4) o.total() 24 -default order is "lex", lexicographic-order o.next() [ 0, 1, 2, 3 ] o.hasNext() true o.next() [ 0, 1, 3, 2 ] +default order is "lex", lexicographic-order o.rewind() [ 0, 1, 2, 3 ] [ 0, 1, 3, 2 ] @@ -35,6 +35,7 @@ o.rewind() [ 3, 1, 2, 0 ] [ 3, 2, 0, 1 ] [ 3, 2, 1, 0 ] +backwards o.forward() [ 3, 2, 1, 0 ] [ 3, 2, 0, 1 ] @@ -60,7 +61,32 @@ o.forward() [ 0, 2, 1, 3 ] [ 0, 1, 3, 2 ] [ 0, 1, 2, 3 ] -o.order("revlex") +o.order("lex,reflected") +[ 3, 2, 1, 0 ] +[ 2, 3, 1, 0 ] +[ 3, 1, 2, 0 ] +[ 1, 3, 2, 0 ] +[ 2, 1, 3, 0 ] +[ 1, 2, 3, 0 ] +[ 3, 2, 0, 1 ] +[ 2, 3, 0, 1 ] +[ 3, 0, 2, 1 ] +[ 0, 3, 2, 1 ] +[ 2, 0, 3, 1 ] +[ 0, 2, 3, 1 ] +[ 3, 1, 0, 2 ] +[ 1, 3, 0, 2 ] +[ 3, 0, 1, 2 ] +[ 0, 3, 1, 2 ] +[ 1, 0, 3, 2 ] +[ 0, 1, 3, 2 ] +[ 2, 1, 0, 3 ] +[ 1, 2, 0, 3 ] +[ 2, 0, 1, 3 ] +[ 0, 2, 1, 3 ] +[ 1, 0, 2, 3 ] +[ 0, 1, 2, 3 ] +o.order("lex,reversed") [ 3, 2, 1, 0 ] [ 3, 2, 0, 1 ] [ 3, 1, 2, 0 ] @@ -110,7 +136,32 @@ o.order("colex") [ 0, 2, 1, 3 ] [ 1, 0, 2, 3 ] [ 0, 1, 2, 3 ] -o.order("revcolex") +o.order("colex,reflected") +[ 0, 1, 2, 3 ] +[ 0, 1, 3, 2 ] +[ 0, 2, 1, 3 ] +[ 0, 2, 3, 1 ] +[ 0, 3, 1, 2 ] +[ 0, 3, 2, 1 ] +[ 1, 0, 2, 3 ] +[ 1, 0, 3, 2 ] +[ 1, 2, 0, 3 ] +[ 1, 2, 3, 0 ] +[ 1, 3, 0, 2 ] +[ 1, 3, 2, 0 ] +[ 2, 0, 1, 3 ] +[ 2, 0, 3, 1 ] +[ 2, 1, 0, 3 ] +[ 2, 1, 3, 0 ] +[ 2, 3, 0, 1 ] +[ 2, 3, 1, 0 ] +[ 3, 0, 1, 2 ] +[ 3, 0, 2, 1 ] +[ 3, 1, 0, 2 ] +[ 3, 1, 2, 0 ] +[ 3, 2, 0, 1 ] +[ 3, 2, 1, 0 ] +o.order("colex,reversed") [ 0, 1, 2, 3 ] [ 1, 0, 2, 3 ] [ 0, 2, 1, 3 ] @@ -135,48 +186,73 @@ o.order("revcolex") [ 3, 1, 2, 0 ] [ 2, 3, 1, 0 ] [ 3, 2, 1, 0 ] -o.random() -[ 3, 0, 2, 1 ] +o.order("minimal") +[ 0, 1, 1, 1 ] +[ 0, 1, 2, 3 ] +[ 0, 2, 3, 2 ] +[ 0, 2, 1, 2 ] +[ 0, 3, 2, 1 ] +[ 0, 3, 3, 3 ] +[ 1, 3, 2, 1 ] +[ 1, 3, 3, 3 ] +[ 1, 1, 2, 3 ] +[ 1, 1, 1, 1 ] +[ 1, 2, 1, 2 ] +[ 1, 2, 3, 2 ] +[ 2, 2, 1, 2 ] +[ 2, 2, 3, 2 ] +[ 2, 3, 3, 3 ] +[ 2, 3, 2, 1 ] +[ 2, 1, 1, 1 ] +[ 2, 1, 2, 3 ] +[ 3, 1, 1, 1 ] +[ 3, 1, 2, 3 ] +[ 3, 2, 3, 2 ] +[ 3, 2, 1, 2 ] +[ 3, 3, 2, 1 ] +[ 3, 3, 3, 3 ] o.order("random") -[ 0, 2, 3, 1 ] -[ 0, 2, 1, 3 ] +[ 0, 1, 3, 2 ] [ 0, 3, 1, 2 ] +[ 2, 0, 3, 1 ] +[ 1, 2, 3, 0 ] +[ 2, 0, 1, 3 ] [ 2, 1, 0, 3 ] -[ 1, 2, 0, 3 ] -[ 3, 1, 0, 2 ] -[ 3, 0, 1, 2 ] -[ 0, 3, 2, 1 ] -[ 0, 1, 3, 2 ] [ 2, 3, 0, 1 ] +[ 0, 2, 3, 1 ] [ 1, 0, 2, 3 ] -[ 1, 0, 3, 2 ] -[ 2, 3, 1, 0 ] -[ 0, 1, 2, 3 ] -[ 2, 0, 1, 3 ] -[ 1, 2, 3, 0 ] -[ 2, 1, 3, 0 ] [ 3, 1, 2, 0 ] -[ 1, 3, 0, 2 ] -[ 3, 2, 1, 0 ] -[ 2, 0, 3, 1 ] +[ 2, 1, 3, 0 ] +[ 2, 3, 1, 0 ] +[ 0, 3, 2, 1 ] +[ 3, 0, 1, 2 ] +[ 3, 2, 0, 1 ] [ 3, 0, 2, 1 ] [ 1, 3, 2, 0 ] -[ 3, 2, 0, 1 ] +[ 3, 1, 0, 2 ] +[ 0, 2, 1, 3 ] +[ 1, 3, 0, 2 ] +[ 3, 2, 1, 0 ] +[ 0, 1, 2, 3 ] +[ 1, 2, 0, 3 ] +[ 1, 0, 3, 2 ] +o.random() +[ 0, 3, 1, 2 ] o.order("colex").range(-5, -1) -[ [ 1, 2, 0, 3 ], - [ 2, 0, 1, 3 ], - [ 0, 2, 1, 3 ], - [ 1, 0, 2, 3 ], - [ 0, 1, 2, 3 ] ] +[ 1, 2, 0, 3 ] +[ 2, 0, 1, 3 ] +[ 0, 2, 1, 3 ] +[ 1, 0, 2, 3 ] +[ 0, 1, 2, 3 ] o.order("stochastic", [ [ 0, 1, 0, 0 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ], [ 1/3, 0, 1/3, 1/3 ] ]).range(0, 9) -[ [ 1, 0, 2, 3 ], - [ 1, 3, 0, 2 ], - [ 1, 2, 3, 0 ], - [ 1, 0, 3, 2 ], - [ 1, 2, 3, 0 ], - [ 1, 0, 3, 2 ], - [ 1, 0, 3, 2 ], - [ 1, 3, 0, 2 ], - [ 1, 3, 2, 0 ], - [ 1, 3, 0, 2 ] ] +[ 1, 0, 2, 3 ] +[ 1, 0, 3, 2 ] +[ 1, 0, 2, 3 ] +[ 1, 2, 0, 3 ] +[ 1, 0, 3, 2 ] +[ 1, 3, 2, 0 ] +[ 1, 3, 2, 0 ] +[ 1, 3, 2, 0 ] +[ 1, 2, 0, 3 ] +[ 1, 0, 3, 2 ] o.dispose() diff --git a/test/subsets.js b/test/subsets.js index c60b21e..765129e 100644 --- a/test/subsets.js +++ b/test/subsets.js @@ -1,6 +1,16 @@ var isNode = 'undefined' !== typeof global && '[object global]' === {}.toString.call(global); var Abacus = isNode ? require('../src/js/Abacus.js') : window.Abacus, echo = console.log; +function print_all( o, prev ) +{ + if ( -1 === prev ) + while ( o.hasPrev() ) echo( o.prev() ); + else + //while ( o.hasNext() ) echo( o.next() ); + // iterator/iterable are supported + for(let item of o) echo( item ); +} + // Note: Due to the large number of combinatorial samples, // Abacus combinatorics use an Iterator pattern to succesively and consistently // generate all combinatorial objects without storing all of them in memory at once @@ -10,14 +20,12 @@ echo('Abacus.Subsets (VERSION = '+Abacus.VERSION+')'); echo('---'); // Powersets -echo('o = Abacus.Subset(4)'); -o = Abacus.Subset(4); +echo('o = Abacus.Subset(3)'); +o = Abacus.Subset(3); echo('o.total()'); echo(o.total()); -echo('default order is "lex", lexicographic-order'); - echo('o.next()'); echo(o.next()); @@ -26,37 +34,37 @@ echo(o.hasNext()); echo('o.next()'); echo(o.next()); - +echo('default order is "lex", lexicographic-order'); echo('o.rewind()'); -o.rewind(); -while (o.hasNext()) echo (o.next()); +print_all( o.rewind() ); +echo('backwards'); echo('o.forward()'); -o.forward(); -while (o.hasPrev()) echo (o.prev()); +print_all( o.forward(), -1 ); -echo('o.order("revlex")'); -o.order("revlex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("lex,reflected")'); +print_all( o.order("lex,reflected") ); + +echo('o.order("lex,reversed")'); +print_all( o.order("lex,reversed") ); echo('o.order("colex")'); -o.order("colex"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("colex") ); + +echo('o.order("colex,reversed")'); +print_all( o.order("colex,reversed") ); -echo('o.order("revcolex")'); -o.order("revcolex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("gray")'); +print_all( o.order("gray") ); +echo('o.order("random")'); +print_all( o.order("random") ); echo('o.random()'); echo(o.random()); -echo('o.order("random")'); -o.order("random"); -while (o.hasNext()) echo (o.next()); - echo('o.order("colex").range(-5, -1)'); -echo (o.order("colex").range(-5, -1)); +print_all(o.order("colex").range(-5, -1)); // dispose diff --git a/test/subsets.txt b/test/subsets.txt index fe506c2..1fff719 100644 --- a/test/subsets.txt +++ b/test/subsets.txt @@ -1,63 +1,49 @@ Abacus.Subsets (VERSION = 0.1.0) --- -o = Abacus.Subset(4) +o = Abacus.Subset(3) o.total() -16 -default order is "lex", lexicographic-order +8 o.next() [] o.hasNext() true o.next() [ 0 ] +default order is "lex", lexicographic-order o.rewind() [] [ 0 ] [ 1 ] -[ 1, 0 ] +[ 0, 1 ] [ 2 ] -[ 2, 0 ] -[ 2, 1 ] -[ 2, 1, 0 ] -[ 3 ] -[ 3, 0 ] -[ 3, 1 ] -[ 3, 1, 0 ] -[ 3, 2 ] -[ 3, 2, 0 ] -[ 3, 2, 1 ] -[ 3, 2, 1, 0 ] +[ 0, 2 ] +[ 1, 2 ] +[ 0, 1, 2 ] +backwards o.forward() -[ 3, 2, 1, 0 ] -[ 3, 2, 1 ] -[ 3, 2, 0 ] -[ 3, 2 ] -[ 3, 1, 0 ] -[ 3, 1 ] -[ 3, 0 ] -[ 3 ] -[ 2, 1, 0 ] -[ 2, 1 ] -[ 2, 0 ] +[ 0, 1, 2 ] +[ 1, 2 ] +[ 0, 2 ] [ 2 ] -[ 1, 0 ] +[ 0, 1 ] [ 1 ] [ 0 ] [] -o.order("revlex") -[ 3, 2, 1, 0 ] -[ 3, 2, 1 ] -[ 3, 2, 0 ] -[ 3, 2 ] -[ 3, 1, 0 ] -[ 3, 1 ] -[ 3, 0 ] -[ 3 ] -[ 2, 1, 0 ] -[ 2, 1 ] +o.order("lex,reflected") +[] +[ 0 ] +[ 1 ] +[ 1, 0 ] +[ 2 ] [ 2, 0 ] +[ 2, 1 ] +[ 2, 1, 0 ] +o.order("lex,reversed") +[ 0, 1, 2 ] +[ 1, 2 ] +[ 0, 2 ] [ 2 ] -[ 1, 0 ] +[ 0, 1 ] [ 1 ] [ 0 ] [] @@ -70,23 +56,7 @@ o.order("colex") [ 0, 2 ] [ 1, 2 ] [ 0, 1, 2 ] -[ 3 ] -[ 0, 3 ] -[ 1, 3 ] -[ 0, 1, 3 ] -[ 2, 3 ] -[ 0, 2, 3 ] -[ 1, 2, 3 ] -[ 0, 1, 2, 3 ] -o.order("revcolex") -[ 0, 1, 2, 3 ] -[ 1, 2, 3 ] -[ 0, 2, 3 ] -[ 2, 3 ] -[ 0, 1, 3 ] -[ 1, 3 ] -[ 0, 3 ] -[ 3 ] +o.order("colex,reversed") [ 0, 1, 2 ] [ 1, 2 ] [ 0, 2 ] @@ -95,25 +65,30 @@ o.order("revcolex") [ 1 ] [ 0 ] [] -o.random() -[ 2, 1 ] +o.order("gray") +[ 2 ] +[ 0, 2 ] +[ 0, 1, 2 ] +[ 1, 2 ] +[ 1 ] +[ 0, 1 ] +[ 0 ] +[] o.order("random") -[ 3, 2, 0 ] +[] [ 0 ] -[ 2, 1 ] -[ 3 ] -[ 2, 0 ] +[ 0, 2 ] [ 1 ] -[ 2, 1, 0 ] -[ 3, 0 ] -[ 3, 2, 1 ] -[ 3, 1 ] +[ 1, 2 ] +[ 0, 1 ] +[ 0, 1, 2 ] [ 2 ] -[ 1, 0 ] -[] -[ 3, 2, 1, 0 ] -[ 3, 1, 0 ] -[ 3, 2 ] +o.random() +[ 0 ] o.order("colex").range(-5, -1) -[ [ 2 ], [ 0, 2 ], [ 1, 2 ], [ 0, 1, 2 ], [ 3 ] ] +[ 2 ] +[ 0, 2 ] +[ 1, 2 ] +[ 0, 1, 2 ] +null o.dispose() diff --git a/test/tensors.js b/test/tensors.js index 869bee8..08e9b06 100644 --- a/test/tensors.js +++ b/test/tensors.js @@ -1,6 +1,16 @@ var isNode = 'undefined' !== typeof global && '[object global]' === {}.toString.call(global); var Abacus = isNode ? require('../src/js/Abacus.js') : window.Abacus, echo = console.log; +function print_all( o, prev ) +{ + if ( -1 === prev ) + while ( o.hasPrev() ) echo( o.prev() ); + else + //while ( o.hasNext() ) echo( o.next() ); + // iterator/iterable are supported + for(let item of o) echo( item ); +} + // Note: Due to the large number of combinatorial samples, // Abacus combinatorics use an Iterator pattern to succesively and consistently // generate all combinatorial objects without storing all of them in memory at once @@ -16,8 +26,6 @@ o = Abacus.Tensor(1,2,3); echo('o.total()'); echo(o.total()); -echo('default order is "lex", lexicographic-order'); - echo('o.next()'); echo(o.next()); @@ -26,37 +34,40 @@ echo(o.hasNext()); echo('o.next()'); echo(o.next()); - +echo('default order is "lex", lexicographic-order'); echo('o.rewind()'); -o.rewind(); -while (o.hasNext()) echo (o.next()); +print_all( o.rewind() ); +echo('backwards'); echo('o.forward()'); -o.forward(); -while (o.hasPrev()) echo (o.prev()); +print_all( o.forward(), -1 ); + +echo('o.order("lex,reflected")'); +print_all( o.order("lex,reflected") ); -echo('o.order("revlex")'); -o.order("revlex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("lex,reversed")'); +print_all( o.order("lex,reversed") ); echo('o.order("colex")'); -o.order("colex"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("colex") ); -echo('o.order("revcolex")'); -o.order("revcolex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("colex,reflected")'); +print_all( o.order("colex,reflected") ); +echo('o.order("colex,reversed")'); +print_all( o.order("colex,reversed") ); -echo('o.random()'); -echo(o.random()); +echo('o.order("gray")'); +print_all( o.order("gray") ); echo('o.order("random")'); -o.order("random"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("random") ); + +echo('o.random()'); +echo(o.random()); echo('o.order("colex").range(-5, -1)'); -echo (o.order("colex").range(-5, -1)); +print_all(o.order("colex").range(-5, -1)); // dispose diff --git a/test/tensors.txt b/test/tensors.txt index 98f258b..5fb1bd5 100644 --- a/test/tensors.txt +++ b/test/tensors.txt @@ -3,13 +3,13 @@ Abacus.Tensors (VERSION = 0.1.0) o = Abacus.Tensor(1,2,3) o.total() 6 -default order is "lex", lexicographic-order o.next() [ 0, 0, 0 ] o.hasNext() true o.next() [ 0, 0, 1 ] +default order is "lex", lexicographic-order o.rewind() [ 0, 0, 0 ] [ 0, 0, 1 ] @@ -17,6 +17,7 @@ o.rewind() [ 0, 1, 0 ] [ 0, 1, 1 ] [ 0, 1, 2 ] +backwards o.forward() [ 0, 1, 2 ] [ 0, 1, 1 ] @@ -24,7 +25,14 @@ o.forward() [ 0, 0, 2 ] [ 0, 0, 1 ] [ 0, 0, 0 ] -o.order("revlex") +o.order("lex,reflected") +[ 0, 0, 0 ] +[ 1, 0, 0 ] +[ 2, 0, 0 ] +[ 0, 1, 0 ] +[ 1, 1, 0 ] +[ 2, 1, 0 ] +o.order("lex,reversed") [ 0, 1, 2 ] [ 0, 1, 1 ] [ 0, 1, 0 ] @@ -33,27 +41,45 @@ o.order("revlex") [ 0, 0, 0 ] o.order("colex") [ 0, 0, 0 ] +[ 1, 0, 0 ] +[ 2, 0, 0 ] +[ 0, 1, 0 ] +[ 1, 1, 0 ] +[ 2, 1, 0 ] +o.order("colex,reflected") +[ 0, 0, 0 ] [ 0, 0, 1 ] [ 0, 0, 2 ] [ 0, 1, 0 ] [ 0, 1, 1 ] [ 0, 1, 2 ] -o.order("revcolex") -[ 0, 1, 2 ] -[ 0, 1, 1 ] +o.order("colex,reversed") +[ 2, 1, 0 ] +[ 1, 1, 0 ] [ 0, 1, 0 ] -[ 0, 0, 2 ] -[ 0, 0, 1 ] +[ 2, 0, 0 ] +[ 1, 0, 0 ] [ 0, 0, 0 ] -o.random() -[ 0, 1, 2 ] -o.order("random") -[ 0, 0, 1 ] +o.order("gray") +[ 0, 1, 0 ] +[ 0, 1, 0 ] +[ 0, 1, 0 ] [ 0, 0, 0 ] -[ 0, 1, 2 ] +[ 0, 0, 0 ] +[ 0, 0, 0 ] +o.order("random") [ 0, 0, 2 ] [ 0, 1, 0 ] +[ 0, 1, 2 ] +[ 0, 1, 1 ] +[ 0, 0, 0 ] +[ 0, 0, 1 ] +o.random() [ 0, 1, 1 ] o.order("colex").range(-5, -1) -[ [ 0, 0, 1 ], [ 0, 0, 2 ], [ 0, 1, 0 ], [ 0, 1, 1 ], [ 0, 1, 2 ] ] +[ 1, 0, 0 ] +[ 2, 0, 0 ] +[ 0, 1, 0 ] +[ 1, 1, 0 ] +[ 2, 1, 0 ] o.dispose() diff --git a/test/test.bat b/test/test.bat index 80c90c7..8a96a63 100644 --- a/test/test.bat +++ b/test/test.bat @@ -4,8 +4,8 @@ call node permutations.js > permutations.txt call node permutations-bigint.js > permutations-bigint.txt call node combinations.js > combinations.txt call node combinations_repeats.js > combinations_repeats.txt -call node subsets.js > subsets.txt -call node partitions.js > partitions.txt +rem call node subsets.js > subsets.txt +rem call node partitions.js > partitions.txt call node tensors.js > tensors.txt call node tuples.js > tuples.txt diff --git a/test/tuples.js b/test/tuples.js index 1314814..48efd01 100644 --- a/test/tuples.js +++ b/test/tuples.js @@ -1,6 +1,16 @@ var isNode = 'undefined' !== typeof global && '[object global]' === {}.toString.call(global); var Abacus = isNode ? require('../src/js/Abacus.js') : window.Abacus, echo = console.log; +function print_all( o, prev ) +{ + if ( -1 === prev ) + while ( o.hasPrev() ) echo( o.prev() ); + else + //while ( o.hasNext() ) echo( o.next() ); + // iterator/iterable are supported + for(let item of o) echo( item ); +} + // Note: Due to the large number of combinatorial samples, // Abacus combinatorics use an Iterator pattern to succesively and consistently // generate all combinatorial objects without storing all of them in memory at once @@ -16,8 +26,6 @@ o = Abacus.Tuple(3,3); echo('o.total()'); echo(o.total()); -echo('default order is "lex", lexicographic-order'); - echo('o.next()'); echo(o.next()); @@ -26,37 +34,40 @@ echo(o.hasNext()); echo('o.next()'); echo(o.next()); - +echo('default order is "lex", lexicographic-order'); echo('o.rewind()'); -o.rewind(); -while (o.hasNext()) echo (o.next()); +print_all( o.rewind() ); +echo('backwards'); echo('o.forward()'); -o.forward(); -while (o.hasPrev()) echo (o.prev()); +print_all( o.forward(), -1 ); + +echo('o.order("lex,reflected")'); +print_all( o.order("lex,reflected") ); -echo('o.order("revlex")'); -o.order("revlex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("lex,reversed")'); +print_all( o.order("lex,reversed") ); echo('o.order("colex")'); -o.order("colex"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("colex") ); -echo('o.order("revcolex")'); -o.order("revcolex"); -while (o.hasNext()) echo (o.next()); +echo('o.order("colex,reflected")'); +print_all( o.order("colex,reflected") ); +echo('o.order("colex,reversed")'); +print_all( o.order("colex,reversed") ); -echo('o.random()'); -echo(o.random()); +echo('o.order("gray")'); +print_all( o.order("gray") ); echo('o.order("random")'); -o.order("random"); -while (o.hasNext()) echo (o.next()); +print_all( o.order("random") ); + +echo('o.random()'); +echo(o.random()); echo('o.order("colex").range(-5, -1)'); -echo (o.order("colex").range(-5, -1)); +print_all(o.order("colex").range(-5, -1)); // dispose diff --git a/test/tuples.txt b/test/tuples.txt index 3db8157..e98c433 100644 --- a/test/tuples.txt +++ b/test/tuples.txt @@ -3,13 +3,13 @@ Abacus.Tuples (VERSION = 0.1.0) o = Abacus.Tuple(3,3) o.total() 27 -default order is "lex", lexicographic-order o.next() [ 0, 0, 0 ] o.hasNext() true o.next() [ 0, 0, 1 ] +default order is "lex", lexicographic-order o.rewind() [ 0, 0, 0 ] [ 0, 0, 1 ] @@ -38,6 +38,7 @@ o.rewind() [ 2, 2, 0 ] [ 2, 2, 1 ] [ 2, 2, 2 ] +backwards o.forward() [ 2, 2, 2 ] [ 2, 2, 1 ] @@ -66,7 +67,35 @@ o.forward() [ 0, 0, 2 ] [ 0, 0, 1 ] [ 0, 0, 0 ] -o.order("revlex") +o.order("lex,reflected") +[ 0, 0, 0 ] +[ 1, 0, 0 ] +[ 2, 0, 0 ] +[ 0, 1, 0 ] +[ 1, 1, 0 ] +[ 2, 1, 0 ] +[ 0, 2, 0 ] +[ 1, 2, 0 ] +[ 2, 2, 0 ] +[ 0, 0, 1 ] +[ 1, 0, 1 ] +[ 2, 0, 1 ] +[ 0, 1, 1 ] +[ 1, 1, 1 ] +[ 2, 1, 1 ] +[ 0, 2, 1 ] +[ 1, 2, 1 ] +[ 2, 2, 1 ] +[ 0, 0, 2 ] +[ 1, 0, 2 ] +[ 2, 0, 2 ] +[ 0, 1, 2 ] +[ 1, 1, 2 ] +[ 2, 1, 2 ] +[ 0, 2, 2 ] +[ 1, 2, 2 ] +[ 2, 2, 2 ] +o.order("lex,reversed") [ 2, 2, 2 ] [ 2, 2, 1 ] [ 2, 2, 0 ] @@ -122,7 +151,35 @@ o.order("colex") [ 0, 2, 2 ] [ 1, 2, 2 ] [ 2, 2, 2 ] -o.order("revcolex") +o.order("colex,reflected") +[ 0, 0, 0 ] +[ 0, 0, 1 ] +[ 0, 0, 2 ] +[ 0, 1, 0 ] +[ 0, 1, 1 ] +[ 0, 1, 2 ] +[ 0, 2, 0 ] +[ 0, 2, 1 ] +[ 0, 2, 2 ] +[ 1, 0, 0 ] +[ 1, 0, 1 ] +[ 1, 0, 2 ] +[ 1, 1, 0 ] +[ 1, 1, 1 ] +[ 1, 1, 2 ] +[ 1, 2, 0 ] +[ 1, 2, 1 ] +[ 1, 2, 2 ] +[ 2, 0, 0 ] +[ 2, 0, 1 ] +[ 2, 0, 2 ] +[ 2, 1, 0 ] +[ 2, 1, 1 ] +[ 2, 1, 2 ] +[ 2, 2, 0 ] +[ 2, 2, 1 ] +[ 2, 2, 2 ] +o.order("colex,reversed") [ 2, 2, 2 ] [ 1, 2, 2 ] [ 0, 2, 2 ] @@ -150,36 +207,68 @@ o.order("revcolex") [ 2, 0, 0 ] [ 1, 0, 0 ] [ 0, 0, 0 ] -o.random() -[ 0, 1, 1 ] -o.order("random") -[ 2, 0, 0 ] -[ 1, 0, 1 ] -[ 1, 0, 2 ] +o.order("gray") +[ 0, 0, 0 ] +[ 0, 0, 1 ] +[ 0, 0, 2 ] +[ 0, 1, 2 ] [ 0, 1, 0 ] +[ 0, 1, 1 ] [ 0, 2, 1 ] -[ 1, 1, 1 ] -[ 2, 1, 0 ] [ 0, 2, 2 ] -[ 0, 0, 2 ] +[ 0, 2, 0 ] +[ 1, 2, 0 ] +[ 1, 2, 1 ] +[ 1, 2, 2 ] +[ 1, 0, 2 ] +[ 1, 0, 0 ] +[ 1, 0, 1 ] +[ 1, 1, 1 ] +[ 1, 1, 2 ] [ 1, 1, 0 ] -[ 2, 0, 2 ] +[ 2, 1, 0 ] [ 2, 1, 1 ] -[ 2, 2, 0 ] -[ 1, 0, 0 ] -[ 0, 1, 1 ] -[ 1, 2, 2 ] -[ 2, 0, 1 ] -[ 0, 1, 2 ] -[ 0, 0, 1 ] [ 2, 1, 2 ] -[ 0, 2, 0 ] +[ 2, 2, 2 ] +[ 2, 2, 0 ] [ 2, 2, 1 ] -[ 1, 1, 2 ] +[ 2, 0, 1 ] +[ 2, 0, 2 ] +[ 2, 0, 0 ] +o.order("random") +[ 2, 0, 2 ] +[ 2, 0, 0 ] +[ 2, 0, 1 ] +[ 2, 1, 0 ] +[ 1, 0, 2 ] +[ 1, 1, 0 ] +[ 0, 0, 2 ] [ 1, 2, 0 ] -[ 2, 2, 2 ] +[ 2, 2, 1 ] +[ 2, 1, 1 ] +[ 1, 0, 1 ] +[ 0, 2, 2 ] +[ 1, 2, 2 ] [ 1, 2, 1 ] +[ 2, 1, 2 ] +[ 2, 2, 2 ] +[ 1, 0, 0 ] [ 0, 0, 0 ] +[ 2, 2, 0 ] +[ 0, 1, 0 ] +[ 1, 1, 2 ] +[ 0, 2, 1 ] +[ 0, 0, 1 ] +[ 0, 2, 0 ] +[ 1, 1, 1 ] +[ 0, 1, 2 ] +[ 0, 1, 1 ] +o.random() +[ 1, 1, 1 ] o.order("colex").range(-5, -1) -[ [ 1, 1, 2 ], [ 2, 1, 2 ], [ 0, 2, 2 ], [ 1, 2, 2 ], [ 2, 2, 2 ] ] +[ 1, 1, 2 ] +[ 2, 1, 2 ] +[ 0, 2, 2 ] +[ 1, 2, 2 ] +[ 2, 2, 2 ] o.dispose()