Better code structure. Better README. Added generation of IIFE file
This commit is contained in:
parent
cfb207db5f
commit
d6d34b4466
|
@ -0,0 +1,178 @@
|
|||
var bigintModArith = (function (exports) {
|
||||
'use strict';
|
||||
|
||||
const _ZERO = BigInt(0);
|
||||
const _ONE = BigInt(1);
|
||||
const _TWO = BigInt(2);
|
||||
|
||||
/**
|
||||
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
|
||||
*
|
||||
* @param {number|bigint} a
|
||||
*
|
||||
* @returns {bigint} the absolute value of a
|
||||
*/
|
||||
function abs(a) {
|
||||
a = BigInt(a);
|
||||
return (a >= _ZERO) ? a : -a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
||||
* @property {bigint} g
|
||||
* @property {bigint} x
|
||||
* @property {bigint} y
|
||||
*/
|
||||
/**
|
||||
* An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
|
||||
* Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
|
||||
*
|
||||
* @param {number|bigint} a
|
||||
* @param {number|bigint} b
|
||||
*
|
||||
* @returns {egcdReturn}
|
||||
*/
|
||||
function eGcd(a, b) {
|
||||
a = BigInt(a);
|
||||
b = BigInt(b);
|
||||
let x = _ZERO;
|
||||
let y = _ONE;
|
||||
let u = _ONE;
|
||||
let v = _ZERO;
|
||||
|
||||
while (a !== _ZERO) {
|
||||
let q = b / a;
|
||||
let r = b % a;
|
||||
let m = x - (u * q);
|
||||
let n = y - (v * q);
|
||||
b = a;
|
||||
a = r;
|
||||
x = u;
|
||||
y = v;
|
||||
u = m;
|
||||
v = n;
|
||||
}
|
||||
return {
|
||||
b: b,
|
||||
x: x,
|
||||
y: y
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
||||
*
|
||||
* @param {number|bigint} a
|
||||
* @param {number|bigint} b
|
||||
*
|
||||
* @returns {bigint} The greatest common divisor of a and b
|
||||
*/
|
||||
function gcd(a, b) {
|
||||
a = abs(a);
|
||||
b = abs(b);
|
||||
let shift = _ZERO;
|
||||
while (!((a | b) & _ONE)) {
|
||||
a >>= _ONE;
|
||||
b >>= _ONE;
|
||||
shift++;
|
||||
}
|
||||
while (!(a & _ONE)) a >>= _ONE;
|
||||
do {
|
||||
while (!(b & _ONE)) b >>= _ONE;
|
||||
if (a > b) {
|
||||
let x = a;
|
||||
a = b;
|
||||
b = x;
|
||||
}
|
||||
b -= a;
|
||||
} while (b);
|
||||
|
||||
// rescale
|
||||
return a << shift;
|
||||
}
|
||||
|
||||
/**
|
||||
* The least common multiple computed as abs(a*b)/gcd(a,b)
|
||||
* @param {number|bigint} a
|
||||
* @param {number|bigint} b
|
||||
*
|
||||
* @returns {bigint} The least common multiple of a and b
|
||||
*/
|
||||
function lcm(a, b) {
|
||||
a = BigInt(a);
|
||||
b = BigInt(b);
|
||||
return abs(a * b) / gcd(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modular inverse.
|
||||
*
|
||||
* @param {number|bigint} a The number to find an inverse for
|
||||
* @param {number|bigint} n The modulo
|
||||
*
|
||||
* @returns {bigint} the inverse modulo n
|
||||
*/
|
||||
function modInv(a, n) {
|
||||
let egcd = eGcd(a, n);
|
||||
if (egcd.b !== _ONE) {
|
||||
return null; // modular inverse does not exist
|
||||
} else {
|
||||
return toZn(egcd.x, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modular exponentiation a**b mod n
|
||||
* @param {number|bigint} a base
|
||||
* @param {number|bigint} b exponent
|
||||
* @param {number|bigint} n modulo
|
||||
*
|
||||
* @returns {bigint} a**b mod n
|
||||
*/
|
||||
function modPow(a, b, n) {
|
||||
// See Knuth, volume 2, section 4.6.3.
|
||||
n = BigInt(n);
|
||||
a = toZn(a, n);
|
||||
b = BigInt(b);
|
||||
if (b < _ZERO) {
|
||||
return modInv(modPow(a, abs(b), n), n);
|
||||
}
|
||||
let result = _ONE;
|
||||
let x = a;
|
||||
while (b > 0) {
|
||||
var leastSignificantBit = b % _TWO;
|
||||
b = b / _TWO;
|
||||
if (leastSignificantBit == _ONE) {
|
||||
result = result * x;
|
||||
result = result % n;
|
||||
}
|
||||
x = x * x;
|
||||
x = x % n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the smallest positive element that is congruent to a in modulo n
|
||||
* @param {number|bigint} a An integer
|
||||
* @param {number|bigint} n The modulo
|
||||
*
|
||||
* @returns {bigint} The smallest positive representation of a in modulo n
|
||||
*/
|
||||
function toZn(a, n) {
|
||||
n = BigInt(n);
|
||||
a = BigInt(a) % n;
|
||||
return (a < 0) ? a + n : a;
|
||||
}
|
||||
|
||||
exports.abs = abs;
|
||||
exports.eGcd = eGcd;
|
||||
exports.gcd = gcd;
|
||||
exports.lcm = lcm;
|
||||
exports.modInv = modInv;
|
||||
exports.modPow = modPow;
|
||||
exports.toZn = toZn;
|
||||
|
||||
return exports;
|
||||
|
||||
}({}));
|
|
@ -0,0 +1 @@
|
|||
var bigintModArith=function(a){'use strict';function c(b){return b=BigInt(b),b>=i?b:-b}function d(c,d){c=BigInt(c),d=BigInt(d);let e=i,f=j,g=j,h=i;for(;c!==i;){let a=d/c,b=d%c,i=e-g*a,j=f-h*a;d=c,c=b,e=g,f=h,g=i,h=j}return{b:d,x:e,y:f}}function e(d,e){d=c(d),e=c(e);let f=i;for(;!((d|e)&j);)d>>=j,e>>=j,f++;for(;!(d&j);)d>>=j;do{for(;!(e&j);)e>>=j;if(d>e){let a=d;d=e,e=a}e-=d}while(e);return d<<f}function f(b,a){let c=d(b,a);return c.b===j?h(c.x,a):null}function g(d,e,l){if(l=BigInt(l),d=h(d,l),e=BigInt(e),e<i)return f(g(d,c(e),l),l);let m=j,o=d;for(;0<e;){var p=e%k;e/=k,p==j&&(m*=o,m%=l),o*=o,o%=l}return m}function h(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b}const i=BigInt(0),j=BigInt(1),k=BigInt(2);return a.abs=c,a.eGcd=d,a.gcd=e,a.lcm=function(d,f){return d=BigInt(d),f=BigInt(f),c(d*f)/e(d,f)},a.modInv=f,a.modPow=g,a.toZn=h,a}({});
|
Loading…
Reference in New Issue