xgcd.js 2.6 KB

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