Barrett.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // BarrettMu, a class for performing Barrett modular reduction computations in
  2. // JavaScript.
  3. //
  4. // Requires BigInt.js.
  5. //
  6. // Copyright 2004-2005 David Shapiro.
  7. //
  8. // You may use, re-use, abuse, copy, and modify this code to your liking, but
  9. // please keep this header.
  10. //
  11. // Thanks!
  12. //
  13. // Dave Shapiro
  14. // dave@ohdave.com
  15. const BigInt = require("./BigInt");
  16. var biCopy = BigInt.biCopy
  17. var biHighIndex = BigInt.biHighIndex
  18. var bigInt = BigInt.bigInt
  19. var biDivide = BigInt.biDivide
  20. function BarrettMu(m)
  21. {
  22. this.modulus = biCopy(m);
  23. this.k = biHighIndex(this.modulus) + 1;
  24. var b2k = new bigInt();
  25. b2k.digits[2 * this.k] = 1; // b2k = b^(2k)
  26. this.mu = biDivide(b2k, this.modulus);
  27. this.bkplus1 = new bigInt();
  28. this.bkplus1.digits[this.k + 1] = 1; // bkplus1 = b^(k+1)
  29. this.modulo = BarrettMu_modulo;
  30. this.multiplyMod = BarrettMu_multiplyMod;
  31. this.powMod = BarrettMu_powMod;
  32. }
  33. function BarrettMu_modulo(x)
  34. {
  35. var q1 = biDivideByRadixPower(x, this.k - 1);
  36. var q2 = biMultiply(q1, this.mu);
  37. var q3 = biDivideByRadixPower(q2, this.k + 1);
  38. var r1 = biModuloByRadixPower(x, this.k + 1);
  39. var r2term = biMultiply(q3, this.modulus);
  40. var r2 = biModuloByRadixPower(r2term, this.k + 1);
  41. var r = biSubtract(r1, r2);
  42. if (r.isNeg) {
  43. r = biAdd(r, this.bkplus1);
  44. }
  45. var rgtem = biCompare(r, this.modulus) >= 0;
  46. while (rgtem) {
  47. r = biSubtract(r, this.modulus);
  48. rgtem = biCompare(r, this.modulus) >= 0;
  49. }
  50. return r;
  51. }
  52. function BarrettMu_multiplyMod(x, y)
  53. {
  54. /*
  55. x = this.modulo(x);
  56. y = this.modulo(y);
  57. */
  58. var xy = biMultiply(x, y);
  59. return this.modulo(xy);
  60. }
  61. function BarrettMu_powMod(x, y)
  62. {
  63. var result = new bigInt();
  64. result.digits[0] = 1;
  65. var a = x;
  66. var k = y;
  67. while (true) {
  68. if ((k.digits[0] & 1) != 0) result = this.multiplyMod(result, a);
  69. k = biShiftRight(k, 1);
  70. if (k.digits[0] == 0 && biHighIndex(k) == 0) break;
  71. a = this.multiplyMod(a, a);
  72. }
  73. return result;
  74. }
  75. module.exports.BarrettMu = BarrettMu