xgcd.js 2.4 KB

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