simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

combinations.js (1237B)


      1 import { isInteger } from '../../utils/number.js';
      2 import { product } from '../../utils/product.js';
      3 export function combinationsNumber(n, k) {
      4   if (!isInteger(n) || n < 0) {
      5     throw new TypeError('Positive integer value expected in function combinations');
      6   }
      7 
      8   if (!isInteger(k) || k < 0) {
      9     throw new TypeError('Positive integer value expected in function combinations');
     10   }
     11 
     12   if (k > n) {
     13     throw new TypeError('k must be less than or equal to n');
     14   }
     15 
     16   var nMinusk = n - k;
     17   var answer = 1;
     18   var firstnumerator = k < nMinusk ? nMinusk + 1 : k + 1;
     19   var nextdivisor = 2;
     20   var lastdivisor = k < nMinusk ? k : nMinusk; // balance multiplications and divisions to try to keep intermediate values
     21   // in exact-integer range as long as possible
     22 
     23   for (var nextnumerator = firstnumerator; nextnumerator <= n; ++nextnumerator) {
     24     answer *= nextnumerator;
     25 
     26     while (nextdivisor <= lastdivisor && answer % nextdivisor === 0) {
     27       answer /= nextdivisor;
     28       ++nextdivisor;
     29     }
     30   } // for big n, k, floating point may have caused weirdness in remainder
     31 
     32 
     33   if (nextdivisor <= lastdivisor) {
     34     answer /= product(nextdivisor, lastdivisor);
     35   }
     36 
     37   return answer;
     38 }
     39 combinationsNumber.signature = 'number, number';