simple-squiggle

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

lcm.js (4871B)


      1 import { factory } from '../../utils/factory.js';
      2 import { createAlgorithm02 } from '../../type/matrix/utils/algorithm02.js';
      3 import { createAlgorithm06 } from '../../type/matrix/utils/algorithm06.js';
      4 import { createAlgorithm11 } from '../../type/matrix/utils/algorithm11.js';
      5 import { createAlgorithm13 } from '../../type/matrix/utils/algorithm13.js';
      6 import { createAlgorithm14 } from '../../type/matrix/utils/algorithm14.js';
      7 import { lcmNumber } from '../../plain/number/index.js';
      8 var name = 'lcm';
      9 var dependencies = ['typed', 'matrix', 'equalScalar'];
     10 export var createLcm = /* #__PURE__ */factory(name, dependencies, _ref => {
     11   var {
     12     typed,
     13     matrix,
     14     equalScalar
     15   } = _ref;
     16   var algorithm02 = createAlgorithm02({
     17     typed,
     18     equalScalar
     19   });
     20   var algorithm06 = createAlgorithm06({
     21     typed,
     22     equalScalar
     23   });
     24   var algorithm11 = createAlgorithm11({
     25     typed,
     26     equalScalar
     27   });
     28   var algorithm13 = createAlgorithm13({
     29     typed
     30   });
     31   var algorithm14 = createAlgorithm14({
     32     typed
     33   });
     34   /**
     35    * Calculate the least common multiple for two or more values or arrays.
     36    *
     37    * lcm is defined as:
     38    *
     39    *     lcm(a, b) = abs(a * b) / gcd(a, b)
     40    *
     41    * For matrices, the function is evaluated element wise.
     42    *
     43    * Syntax:
     44    *
     45    *    math.lcm(a, b)
     46    *    math.lcm(a, b, c, ...)
     47    *
     48    * Examples:
     49    *
     50    *    math.lcm(4, 6)               // returns 12
     51    *    math.lcm(6, 21)              // returns 42
     52    *    math.lcm(6, 21, 5)           // returns 210
     53    *
     54    *    math.lcm([4, 6], [6, 21])    // returns [12, 42]
     55    *
     56    * See also:
     57    *
     58    *    gcd, xgcd
     59    *
     60    * @param {... number | BigNumber | Array | Matrix} args  Two or more integer numbers
     61    * @return {number | BigNumber | Array | Matrix}                           The least common multiple
     62    */
     63 
     64   return typed(name, {
     65     'number, number': lcmNumber,
     66     'BigNumber, BigNumber': _lcmBigNumber,
     67     'Fraction, Fraction': function FractionFraction(x, y) {
     68       return x.lcm(y);
     69     },
     70     'SparseMatrix, SparseMatrix': function SparseMatrixSparseMatrix(x, y) {
     71       return algorithm06(x, y, this);
     72     },
     73     'SparseMatrix, DenseMatrix': function SparseMatrixDenseMatrix(x, y) {
     74       return algorithm02(y, x, this, true);
     75     },
     76     'DenseMatrix, SparseMatrix': function DenseMatrixSparseMatrix(x, y) {
     77       return algorithm02(x, y, this, false);
     78     },
     79     'DenseMatrix, DenseMatrix': function DenseMatrixDenseMatrix(x, y) {
     80       return algorithm13(x, y, this);
     81     },
     82     'Array, Array': function ArrayArray(x, y) {
     83       // use matrix implementation
     84       return this(matrix(x), matrix(y)).valueOf();
     85     },
     86     'Array, Matrix': function ArrayMatrix(x, y) {
     87       // use matrix implementation
     88       return this(matrix(x), y);
     89     },
     90     'Matrix, Array': function MatrixArray(x, y) {
     91       // use matrix implementation
     92       return this(x, matrix(y));
     93     },
     94     'SparseMatrix, number | BigNumber': function SparseMatrixNumberBigNumber(x, y) {
     95       return algorithm11(x, y, this, false);
     96     },
     97     'DenseMatrix, number | BigNumber': function DenseMatrixNumberBigNumber(x, y) {
     98       return algorithm14(x, y, this, false);
     99     },
    100     'number | BigNumber, SparseMatrix': function numberBigNumberSparseMatrix(x, y) {
    101       return algorithm11(y, x, this, true);
    102     },
    103     'number | BigNumber, DenseMatrix': function numberBigNumberDenseMatrix(x, y) {
    104       return algorithm14(y, x, this, true);
    105     },
    106     'Array, number | BigNumber': function ArrayNumberBigNumber(x, y) {
    107       // use matrix implementation
    108       return algorithm14(matrix(x), y, this, false).valueOf();
    109     },
    110     'number | BigNumber, Array': function numberBigNumberArray(x, y) {
    111       // use matrix implementation
    112       return algorithm14(matrix(y), x, this, true).valueOf();
    113     },
    114     // TODO: need a smarter notation here
    115     'Array | Matrix | number | BigNumber, Array | Matrix | number | BigNumber, ...Array | Matrix | number | BigNumber': function ArrayMatrixNumberBigNumberArrayMatrixNumberBigNumberArrayMatrixNumberBigNumber(a, b, args) {
    116       var res = this(a, b);
    117 
    118       for (var i = 0; i < args.length; i++) {
    119         res = this(res, args[i]);
    120       }
    121 
    122       return res;
    123     }
    124   });
    125   /**
    126    * Calculate lcm for two BigNumbers
    127    * @param {BigNumber} a
    128    * @param {BigNumber} b
    129    * @returns {BigNumber} Returns the least common multiple of a and b
    130    * @private
    131    */
    132 
    133   function _lcmBigNumber(a, b) {
    134     if (!a.isInt() || !b.isInt()) {
    135       throw new Error('Parameters in function lcm must be integer numbers');
    136     }
    137 
    138     if (a.isZero()) {
    139       return a;
    140     }
    141 
    142     if (b.isZero()) {
    143       return b;
    144     } // https://en.wikipedia.org/wiki/Euclidean_algorithm
    145     // evaluate lcm here inline to reduce overhead
    146 
    147 
    148     var prod = a.times(b);
    149 
    150     while (!b.isZero()) {
    151       var t = b;
    152       b = a.mod(t);
    153       a = t;
    154     }
    155 
    156     return prod.div(a).abs();
    157   }
    158 });