xgcd.js (2399B)
1 import { factory } from '../../utils/factory.js'; 2 import { xgcdNumber } from '../../plain/number/index.js'; 3 var name = 'xgcd'; 4 var dependencies = ['typed', 'config', 'matrix', 'BigNumber']; 5 export var createXgcd = /* #__PURE__ */factory(name, dependencies, _ref => { 6 var { 7 typed, 8 config, 9 matrix, 10 BigNumber 11 } = _ref; 12 13 /** 14 * Calculate the extended greatest common divisor for two values. 15 * See https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm. 16 * 17 * Syntax: 18 * 19 * math.xgcd(a, b) 20 * 21 * Examples: 22 * 23 * math.xgcd(8, 12) // returns [4, -1, 1] 24 * math.gcd(8, 12) // returns 4 25 * math.xgcd(36163, 21199) // returns [1247, -7, 12] 26 * 27 * See also: 28 * 29 * gcd, lcm 30 * 31 * @param {number | BigNumber} a An integer number 32 * @param {number | BigNumber} b An integer number 33 * @return {Array} Returns an array containing 3 integers `[div, m, n]` 34 * where `div = gcd(a, b)` and `a*m + b*n = div` 35 */ 36 return typed(name, { 37 'number, number': function numberNumber(a, b) { 38 var res = xgcdNumber(a, b); 39 return config.matrix === 'Array' ? res : matrix(res); 40 }, 41 'BigNumber, BigNumber': _xgcdBigNumber // TODO: implement support for Fraction 42 43 }); 44 /** 45 * Calculate xgcd for two BigNumbers 46 * @param {BigNumber} a 47 * @param {BigNumber} b 48 * @return {BigNumber[]} result 49 * @private 50 */ 51 52 function _xgcdBigNumber(a, b) { 53 // source: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm 54 var // used to swap two variables 55 t; 56 var // quotient 57 q; 58 var // remainder 59 r; 60 var zero = new BigNumber(0); 61 var one = new BigNumber(1); 62 var x = zero; 63 var lastx = one; 64 var y = one; 65 var lasty = zero; 66 67 if (!a.isInt() || !b.isInt()) { 68 throw new Error('Parameters in function xgcd must be integer numbers'); 69 } 70 71 while (!b.isZero()) { 72 q = a.div(b).floor(); 73 r = a.mod(b); 74 t = x; 75 x = lastx.minus(q.times(x)); 76 lastx = t; 77 t = y; 78 y = lasty.minus(q.times(y)); 79 lasty = t; 80 a = b; 81 b = r; 82 } 83 84 var res; 85 86 if (a.lt(zero)) { 87 res = [a.neg(), lastx.neg(), lasty.neg()]; 88 } else { 89 res = [a, !a.isZero() ? lastx : 0, lasty]; 90 } 91 92 return config.matrix === 'Array' ? res : matrix(res); 93 } 94 });