bigint-mod-arith
Advanced tools
Comparing version 1.2.5 to 1.3.0
@@ -0,3 +1,4 @@ | ||
'use strict'; | ||
const rollup = require('rollup'); | ||
const commonjs = require('rollup-plugin-commonjs'); | ||
const minify = require('rollup-plugin-babel-minify'); | ||
@@ -8,2 +9,5 @@ const fs = require('fs'); | ||
const rootDir = path.join(__dirname, '..'); | ||
const srcDir = path.join(rootDir, 'src'); | ||
const dstDir = path.join(rootDir, 'dist'); | ||
@@ -13,17 +17,38 @@ const buildOptions = [ | ||
input: { | ||
input: path.join(__dirname, '..', 'src', 'main.js'), | ||
input: path.join(srcDir, 'main.js') | ||
}, | ||
output: { | ||
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.js`), | ||
format: 'iife', | ||
name: camelise(pkgJson.name) | ||
} | ||
}, | ||
{ // Browser minified | ||
input: { | ||
input: path.join(srcDir, 'main.js'), | ||
plugins: [ | ||
commonjs() | ||
minify({ | ||
'comments': false | ||
}) | ||
], | ||
}, | ||
output: { | ||
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.browser.mod.js`), | ||
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.min.js`), | ||
format: 'iife', | ||
name: camelise(pkgJson.name) | ||
} | ||
}, | ||
{ // Browser esm | ||
input: { | ||
input: path.join(srcDir, 'main.js') | ||
}, | ||
output: { | ||
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.mod.js`), | ||
format: 'esm' | ||
} | ||
}, | ||
{ // Browser minified | ||
{ // Browser esm minified | ||
input: { | ||
input: path.join(__dirname, '..', 'src', 'main.js'), | ||
input: path.join(srcDir, 'main.js'), | ||
plugins: [ | ||
commonjs(), | ||
minify({ | ||
@@ -35,3 +60,3 @@ 'comments': false | ||
output: { | ||
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.browser.mod.min.js`), | ||
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.mod.min.js`), | ||
format: 'esm' | ||
@@ -42,9 +67,9 @@ } | ||
input: { | ||
input: path.join(__dirname, '..', 'src', 'main.js'), | ||
input: path.join(srcDir, 'main.js'), | ||
}, | ||
output: { | ||
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.node.js`), | ||
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.node.js`), | ||
format: 'cjs' | ||
} | ||
}, | ||
} | ||
]; | ||
@@ -57,3 +82,2 @@ | ||
/* --- HELPLER FUNCTIONS --- */ | ||
@@ -77,1 +101,8 @@ | ||
} | ||
function camelise(str) { | ||
return str.replace(/-([a-z])/g, | ||
function (m, w) { | ||
return w.toUpperCase(); | ||
}); | ||
} |
@@ -0,1 +1,5 @@ | ||
const _ZERO = BigInt(0); | ||
const _ONE = BigInt(1); | ||
const _TWO = BigInt(2); | ||
/** | ||
@@ -8,8 +12,50 @@ * Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0 | ||
*/ | ||
const abs = function (a) { | ||
function abs(a) { | ||
a = BigInt(a); | ||
return (a >= BigInt(0)) ? a : -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. | ||
@@ -22,14 +68,14 @@ * | ||
*/ | ||
const gcd = function (a, b) { | ||
function gcd(a, b) { | ||
a = abs(a); | ||
b = abs(b); | ||
let shift = BigInt(0); | ||
while (!((a | b) & BigInt(1))) { | ||
a >>= BigInt(1); | ||
b >>= BigInt(1); | ||
let shift = _ZERO; | ||
while (!((a | b) & _ONE)) { | ||
a >>= _ONE; | ||
b >>= _ONE; | ||
shift++; | ||
} | ||
while (!(a & BigInt(1))) a >>= BigInt(1); | ||
while (!(a & _ONE)) a >>= _ONE; | ||
do { | ||
while (!(b & BigInt(1))) b >>= BigInt(1); | ||
while (!(b & _ONE)) b >>= _ONE; | ||
if (a > b) { | ||
@@ -45,3 +91,3 @@ let x = a; | ||
return a << shift; | ||
}; | ||
} | ||
@@ -55,64 +101,9 @@ /** | ||
*/ | ||
const lcm = function (a, b) { | ||
function lcm(a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
return abs(a * b) / gcd(a, b); | ||
}; | ||
} | ||
/** | ||
* 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 | ||
*/ | ||
const toZn = function (a, n) { | ||
n = BigInt(n); | ||
a = BigInt(a) % n; | ||
return (a < 0) ? a + n : 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} | ||
*/ | ||
const eGcd = function (a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
let x = BigInt(0); | ||
let y = BigInt(1); | ||
let u = BigInt(1); | ||
let v = BigInt(0); | ||
while (a !== BigInt(0)) { | ||
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 | ||
}; | ||
}; | ||
/** | ||
* Modular inverse. | ||
@@ -125,5 +116,5 @@ * | ||
*/ | ||
const modInv = function (a, n) { | ||
function modInv(a, n) { | ||
let egcd = eGcd(a, n); | ||
if (egcd.b !== BigInt(1)) { | ||
if (egcd.b !== _ONE) { | ||
return null; // modular inverse does not exist | ||
@@ -133,3 +124,3 @@ } else { | ||
} | ||
}; | ||
} | ||
@@ -144,3 +135,3 @@ /** | ||
*/ | ||
const modPow = function (a, b, n) { | ||
function modPow(a, b, n) { | ||
// See Knuth, volume 2, section 4.6.3. | ||
@@ -150,11 +141,11 @@ n = BigInt(n); | ||
b = BigInt(b); | ||
if (b < BigInt(0)) { | ||
if (b < _ZERO) { | ||
return modInv(modPow(a, abs(b), n), n); | ||
} | ||
let result = BigInt(1); | ||
let result = _ONE; | ||
let x = a; | ||
while (b > 0) { | ||
var leastSignificantBit = b % BigInt(2); | ||
b = b / BigInt(2); | ||
if (leastSignificantBit == BigInt(1)) { | ||
var leastSignificantBit = b % _TWO; | ||
b = b / _TWO; | ||
if (leastSignificantBit == _ONE) { | ||
result = result * x; | ||
@@ -167,18 +158,17 @@ result = result % n; | ||
return result; | ||
}; | ||
} | ||
var main = { | ||
abs: abs, | ||
gcd: gcd, | ||
lcm: lcm, | ||
modInv: modInv, | ||
modPow: modPow | ||
}; | ||
var main_1 = main.abs; | ||
var main_2 = main.gcd; | ||
var main_3 = main.lcm; | ||
var main_4 = main.modInv; | ||
var main_5 = main.modPow; | ||
/** | ||
* 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; | ||
} | ||
export default main; | ||
export { main_1 as abs, main_2 as gcd, main_3 as lcm, main_4 as modInv, main_5 as modPow }; | ||
export { abs, eGcd, gcd, lcm, modInv, modPow, toZn }; |
@@ -1,1 +0,1 @@ | ||
const abs=function(b){return b=BigInt(b),b>=BigInt(0)?b:-b},gcd=function(c,d){c=abs(c),d=abs(d);let e=BigInt(0);for(;!((c|d)&BigInt(1));)c>>=BigInt(1),d>>=BigInt(1),e++;for(;!(c&BigInt(1));)c>>=BigInt(1);do{for(;!(d&BigInt(1));)d>>=BigInt(1);if(c>d){let a=c;c=d,d=a}d-=c}while(d);return c<<e},lcm=function(c,d){return c=BigInt(c),d=BigInt(d),abs(c*d)/gcd(c,d)},toZn=function(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b},eGcd=function(c,d){c=BigInt(c),d=BigInt(d);let e=BigInt(0),f=BigInt(1),g=BigInt(1),h=BigInt(0);for(;c!==BigInt(0);){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}},modInv=function(b,a){let c=eGcd(b,a);return c.b===BigInt(1)?toZn(c.x,a):null},modPow=function(c,d,e){if(e=BigInt(e),c=toZn(c,e),d=BigInt(d),d<BigInt(0))return modInv(modPow(c,abs(d),e),e);let f=BigInt(1),g=c;for(;0<d;){var h=d%BigInt(2);d/=BigInt(2),h==BigInt(1)&&(f*=g,f%=e),g*=g,g%=e}return f};var main={abs:abs,gcd:gcd,lcm:lcm,modInv:modInv,modPow:modPow},main_1=main.abs,main_2=main.gcd,main_3=main.lcm,main_4=main.modInv,main_5=main.modPow;export default main;export{main_1 as abs,main_2 as gcd,main_3 as lcm,main_4 as modInv,main_5 as modPow}; | ||
const _ZERO=BigInt(0),_ONE=BigInt(1),_TWO=BigInt(2);function abs(b){return b=BigInt(b),b>=_ZERO?b:-b}function eGcd(c,d){c=BigInt(c),d=BigInt(d);let e=_ZERO,f=_ONE,g=_ONE,h=_ZERO;for(;c!==_ZERO;){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 gcd(c,d){c=abs(c),d=abs(d);let e=_ZERO;for(;!((c|d)&_ONE);)c>>=_ONE,d>>=_ONE,e++;for(;!(c&_ONE);)c>>=_ONE;do{for(;!(d&_ONE);)d>>=_ONE;if(c>d){let a=c;c=d,d=a}d-=c}while(d);return c<<e}function lcm(c,d){return c=BigInt(c),d=BigInt(d),abs(c*d)/gcd(c,d)}function modInv(b,a){let c=eGcd(b,a);return c.b===_ONE?toZn(c.x,a):null}function modPow(c,d,e){if(e=BigInt(e),c=toZn(c,e),d=BigInt(d),d<_ZERO)return modInv(modPow(c,abs(d),e),e);let f=_ONE,g=c;for(;0<d;){var h=d%_TWO;d/=_TWO,h==_ONE&&(f*=g,f%=e),g*=g,g%=e}return f}function toZn(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b}export{abs,eGcd,gcd,lcm,modInv,modPow,toZn}; |
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
const _ZERO = BigInt(0); | ||
const _ONE = BigInt(1); | ||
const _TWO = BigInt(2); | ||
/** | ||
@@ -10,8 +16,50 @@ * Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0 | ||
*/ | ||
const abs = function (a) { | ||
function abs(a) { | ||
a = BigInt(a); | ||
return (a >= BigInt(0)) ? a : -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. | ||
@@ -24,14 +72,14 @@ * | ||
*/ | ||
const gcd = function (a, b) { | ||
function gcd(a, b) { | ||
a = abs(a); | ||
b = abs(b); | ||
let shift = BigInt(0); | ||
while (!((a | b) & BigInt(1))) { | ||
a >>= BigInt(1); | ||
b >>= BigInt(1); | ||
let shift = _ZERO; | ||
while (!((a | b) & _ONE)) { | ||
a >>= _ONE; | ||
b >>= _ONE; | ||
shift++; | ||
} | ||
while (!(a & BigInt(1))) a >>= BigInt(1); | ||
while (!(a & _ONE)) a >>= _ONE; | ||
do { | ||
while (!(b & BigInt(1))) b >>= BigInt(1); | ||
while (!(b & _ONE)) b >>= _ONE; | ||
if (a > b) { | ||
@@ -47,3 +95,3 @@ let x = a; | ||
return a << shift; | ||
}; | ||
} | ||
@@ -57,64 +105,9 @@ /** | ||
*/ | ||
const lcm = function (a, b) { | ||
function lcm(a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
return abs(a * b) / gcd(a, b); | ||
}; | ||
} | ||
/** | ||
* 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 | ||
*/ | ||
const toZn = function (a, n) { | ||
n = BigInt(n); | ||
a = BigInt(a) % n; | ||
return (a < 0) ? a + n : 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} | ||
*/ | ||
const eGcd = function (a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
let x = BigInt(0); | ||
let y = BigInt(1); | ||
let u = BigInt(1); | ||
let v = BigInt(0); | ||
while (a !== BigInt(0)) { | ||
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 | ||
}; | ||
}; | ||
/** | ||
* Modular inverse. | ||
@@ -127,5 +120,5 @@ * | ||
*/ | ||
const modInv = function (a, n) { | ||
function modInv(a, n) { | ||
let egcd = eGcd(a, n); | ||
if (egcd.b !== BigInt(1)) { | ||
if (egcd.b !== _ONE) { | ||
return null; // modular inverse does not exist | ||
@@ -135,3 +128,3 @@ } else { | ||
} | ||
}; | ||
} | ||
@@ -146,3 +139,3 @@ /** | ||
*/ | ||
const modPow = function (a, b, n) { | ||
function modPow(a, b, n) { | ||
// See Knuth, volume 2, section 4.6.3. | ||
@@ -152,11 +145,11 @@ n = BigInt(n); | ||
b = BigInt(b); | ||
if (b < BigInt(0)) { | ||
if (b < _ZERO) { | ||
return modInv(modPow(a, abs(b), n), n); | ||
} | ||
let result = BigInt(1); | ||
let result = _ONE; | ||
let x = a; | ||
while (b > 0) { | ||
var leastSignificantBit = b % BigInt(2); | ||
b = b / BigInt(2); | ||
if (leastSignificantBit == BigInt(1)) { | ||
var leastSignificantBit = b % _TWO; | ||
b = b / _TWO; | ||
if (leastSignificantBit == _ONE) { | ||
result = result * x; | ||
@@ -169,10 +162,23 @@ result = result % n; | ||
return result; | ||
}; | ||
} | ||
module.exports = { | ||
abs: abs, | ||
gcd: gcd, | ||
lcm: lcm, | ||
modInv: modInv, | ||
modPow: modPow | ||
}; | ||
/** | ||
* 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; |
{ | ||
"name": "bigint-mod-arith", | ||
"version": "1.2.5", | ||
"version": "1.3.0", | ||
"description": "Some additional common functions for modular arithmetics using native JS (stage 3) implementation of BigInt", | ||
@@ -11,3 +11,5 @@ "keywords": [ | ||
"egcd", | ||
"modinv", | ||
"modular inverse", | ||
"modpow", | ||
"modular exponentiation" | ||
@@ -30,9 +32,10 @@ ], | ||
"scripts": { | ||
"docs:build": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md", | ||
"build": "node build/build.rollup.js", | ||
"prepublishOnly": "npm run build && npm run docs:build" | ||
"build:docs": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md", | ||
"build:all": "npm run build && npm run build:docs", | ||
"prepublishOnly": "npm run build && npm run build:docs" | ||
}, | ||
"devDependencies": { | ||
"jsdoc-to-markdown": "^4.0.1", | ||
"rollup": "^1.9.0", | ||
"rollup": "^1.10.1", | ||
"rollup-plugin-babel-minify": "^8.0.0", | ||
@@ -39,0 +42,0 @@ "rollup-plugin-commonjs": "^9.3.4" |
110
README.md
# bigint-mod-arith | ||
Some extra functions to work with modular arithmetics using native JS (stage 3) implementation of BigInt. It can be used | ||
with Node.js (>=10.4.0) and [Web Browsers supporting | ||
BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility). | ||
Some extra functions to work with modular arithmetics using native JS (stage 3) implementation of BigInt. It can be used by any [Web Browser or webview supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) and with Node.js (>=10.4.0). | ||
If you are looking for a cryptographically secure random generator and for probale primes (generation and testing), you | ||
If you are looking for a cryptographically-secure random generator and for strong probable primes (generation and testing), you | ||
may be interested in [bigint-secrets](https://github.com/juanelas/bigint-secrets) | ||
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in | ||
cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html)**_ | ||
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html)._ | ||
Many platforms provide native support for cryptography, such as | ||
[webcrypto](https://w3c.github.io/webcrypto/Overview.html) or [node | ||
crypto](https://nodejs.org/dist/latest/docs/api/crypto.html). | ||
## Installation | ||
bigint-mod-arith is distributed as both an ES6 and a CJS module. | ||
bigint-mod-arith is distributed for [web browsers and/or webviews supporting | ||
BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) | ||
as an ES6 module or an IIFE file; and for Node.js (>=10.4.0), as a CJS module. | ||
The ES6 module is built for any [web browser supporting | ||
BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility). | ||
The module only uses native javascript implementations and no polyfills had been applied. | ||
The CJS module is built as a standard node module. | ||
bigint-mod-arith can be imported to your project with `npm`: | ||
@@ -30,7 +19,7 @@ ```bash | ||
``` | ||
NPM installation defaults to the ES6 module for browsers and the CJS one for Node.js. | ||
For web browsers, you can also [download the bundle from | ||
GitHub](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js). | ||
For web browsers, you can also directly download the minimised version of the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js) from GitHub. | ||
## Usage examples | ||
## Usage example | ||
@@ -41,5 +30,8 @@ With node js: | ||
// Stage 3 BigInts with value 666 can be declared as BigInt('666') | ||
// or the shorter no-linter-friendly new syntax 666n | ||
/* Stage 3 BigInts with value 666 can be declared as BigInt('666') | ||
or the shorter new no-so-linter-friendly syntax 666n. | ||
Notice that you can also pass a number, e.g. BigInt(666), but it is not | ||
recommended since values over 2**53 - 1 won't be safe but no warning will | ||
be raised. | ||
*/ | ||
let a = BigInt('5'); | ||
@@ -49,7 +41,7 @@ let b = BigInt('2'); | ||
console.log(bigintModArith.modPow(a, b, n)); // prints 6 | ||
console.log(bigintCryptoUtils.modPow(a, b, n)); // prints 6 | ||
console.log(bigintModArith.modInv(BigInt('2'), BigInt('5'))); // prints 3 | ||
console.log(bigintCryptoUtils.modInv(BigInt('2'), BigInt('5'))); // prints 3 | ||
console.log(bigintModArith.modInv(BigInt('3'), BigInt('5'))); // prints 2 | ||
console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))); // prints 2 | ||
``` | ||
@@ -61,4 +53,2 @@ | ||
import * as bigintModArith from 'bigint-mod-arith-latest.browser.mod.min.js'; | ||
// Stage 3 BigInts with value 666 can be declared as BigInt('666') | ||
// or the shorter no-linter-friendly new syntax 666n | ||
@@ -85,2 +75,6 @@ let a = BigInt('5'); | ||
</dd> | ||
<dt><a href="#eGcd">eGcd(a, b)</a> ⇒ <code><a href="#egcdReturn">egcdReturn</a></code></dt> | ||
<dd><p>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).</p> | ||
</dd> | ||
<dt><a href="#gcd">gcd(a, b)</a> ⇒ <code>bigint</code></dt> | ||
@@ -92,9 +86,2 @@ <dd><p>Greatest-common divisor of two integers based on the iterative binary algorithm.</p> | ||
</dd> | ||
<dt><a href="#toZn">toZn(a, n)</a> ⇒ <code>bigint</code></dt> | ||
<dd><p>Finds the smallest positive element that is congruent to a in modulo n</p> | ||
</dd> | ||
<dt><a href="#eGcd">eGcd(a, b)</a> ⇒ <code><a href="#egcdReturn">egcdReturn</a></code></dt> | ||
<dd><p>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).</p> | ||
</dd> | ||
<dt><a href="#modInv">modInv(a, n)</a> ⇒ <code>bigint</code></dt> | ||
@@ -106,2 +93,5 @@ <dd><p>Modular inverse.</p> | ||
</dd> | ||
<dt><a href="#toZn">toZn(a, n)</a> ⇒ <code>bigint</code></dt> | ||
<dd><p>Finds the smallest positive element that is congruent to a in modulo n</p> | ||
</dd> | ||
</dl> | ||
@@ -129,9 +119,9 @@ | ||
<a name="gcd"></a> | ||
<a name="eGcd"></a> | ||
## gcd(a, b) ⇒ <code>bigint</code> | ||
Greatest-common divisor of two integers based on the iterative binary algorithm. | ||
## eGcd(a, b) ⇒ [<code>egcdReturn</code>](#egcdReturn) | ||
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). | ||
**Kind**: global function | ||
**Returns**: <code>bigint</code> - The greatest common divisor of a and b | ||
@@ -143,9 +133,9 @@ | Param | Type | | ||
<a name="lcm"></a> | ||
<a name="gcd"></a> | ||
## lcm(a, b) ⇒ <code>bigint</code> | ||
The least common multiple computed as abs(a*b)/gcd(a,b) | ||
## gcd(a, b) ⇒ <code>bigint</code> | ||
Greatest-common divisor of two integers based on the iterative binary algorithm. | ||
**Kind**: global function | ||
**Returns**: <code>bigint</code> - The least common multiple of a and b | ||
**Returns**: <code>bigint</code> - The greatest common divisor of a and b | ||
@@ -157,23 +147,10 @@ | Param | Type | | ||
<a name="toZn"></a> | ||
<a name="lcm"></a> | ||
## toZn(a, n) ⇒ <code>bigint</code> | ||
Finds the smallest positive element that is congruent to a in modulo n | ||
## lcm(a, b) ⇒ <code>bigint</code> | ||
The least common multiple computed as abs(a*b)/gcd(a,b) | ||
**Kind**: global function | ||
**Returns**: <code>bigint</code> - The smallest positive representation of a in modulo n | ||
**Returns**: <code>bigint</code> - The least common multiple of a and b | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| a | <code>number</code> \| <code>bigint</code> | An integer | | ||
| n | <code>number</code> \| <code>bigint</code> | The modulo | | ||
<a name="eGcd"></a> | ||
## eGcd(a, b) ⇒ [<code>egcdReturn</code>](#egcdReturn) | ||
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). | ||
**Kind**: global function | ||
| Param | Type | | ||
@@ -211,2 +188,15 @@ | --- | --- | | ||
<a name="toZn"></a> | ||
## toZn(a, n) ⇒ <code>bigint</code> | ||
Finds the smallest positive element that is congruent to a in modulo n | ||
**Kind**: global function | ||
**Returns**: <code>bigint</code> - The smallest positive representation of a in modulo n | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| a | <code>number</code> \| <code>bigint</code> | An integer | | ||
| n | <code>number</code> \| <code>bigint</code> | The modulo | | ||
<a name="egcdReturn"></a> | ||
@@ -213,0 +203,0 @@ |
166
src/main.js
'use strict'; | ||
const _ZERO = BigInt(0); | ||
const _ONE = BigInt(1); | ||
const _TWO = BigInt(2); | ||
/** | ||
@@ -10,8 +14,50 @@ * Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0 | ||
*/ | ||
const abs = function (a) { | ||
export function abs(a) { | ||
a = BigInt(a); | ||
return (a >= BigInt(0)) ? a : -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} | ||
*/ | ||
export 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. | ||
@@ -24,14 +70,14 @@ * | ||
*/ | ||
const gcd = function (a, b) { | ||
export function gcd(a, b) { | ||
a = abs(a); | ||
b = abs(b); | ||
let shift = BigInt(0); | ||
while (!((a | b) & BigInt(1))) { | ||
a >>= BigInt(1); | ||
b >>= BigInt(1); | ||
let shift = _ZERO; | ||
while (!((a | b) & _ONE)) { | ||
a >>= _ONE; | ||
b >>= _ONE; | ||
shift++; | ||
} | ||
while (!(a & BigInt(1))) a >>= BigInt(1); | ||
while (!(a & _ONE)) a >>= _ONE; | ||
do { | ||
while (!(b & BigInt(1))) b >>= BigInt(1); | ||
while (!(b & _ONE)) b >>= _ONE; | ||
if (a > b) { | ||
@@ -47,3 +93,3 @@ let x = a; | ||
return a << shift; | ||
}; | ||
} | ||
@@ -57,64 +103,9 @@ /** | ||
*/ | ||
const lcm = function (a, b) { | ||
export function lcm(a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
return abs(a * b) / gcd(a, b); | ||
}; | ||
} | ||
/** | ||
* 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 | ||
*/ | ||
const toZn = function (a, n) { | ||
n = BigInt(n); | ||
a = BigInt(a) % n; | ||
return (a < 0) ? a + n : 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} | ||
*/ | ||
const eGcd = function (a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
let x = BigInt(0); | ||
let y = BigInt(1); | ||
let u = BigInt(1); | ||
let v = BigInt(0); | ||
while (a !== BigInt(0)) { | ||
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 | ||
}; | ||
}; | ||
/** | ||
* Modular inverse. | ||
@@ -127,5 +118,5 @@ * | ||
*/ | ||
const modInv = function (a, n) { | ||
export function modInv(a, n) { | ||
let egcd = eGcd(a, n); | ||
if (egcd.b !== BigInt(1)) { | ||
if (egcd.b !== _ONE) { | ||
return null; // modular inverse does not exist | ||
@@ -135,3 +126,3 @@ } else { | ||
} | ||
}; | ||
} | ||
@@ -146,3 +137,3 @@ /** | ||
*/ | ||
const modPow = function (a, b, n) { | ||
export function modPow(a, b, n) { | ||
// See Knuth, volume 2, section 4.6.3. | ||
@@ -152,11 +143,11 @@ n = BigInt(n); | ||
b = BigInt(b); | ||
if (b < BigInt(0)) { | ||
if (b < _ZERO) { | ||
return modInv(modPow(a, abs(b), n), n); | ||
} | ||
let result = BigInt(1); | ||
let result = _ONE; | ||
let x = a; | ||
while (b > 0) { | ||
var leastSignificantBit = b % BigInt(2); | ||
b = b / BigInt(2); | ||
if (leastSignificantBit == BigInt(1)) { | ||
var leastSignificantBit = b % _TWO; | ||
b = b / _TWO; | ||
if (leastSignificantBit == _ONE) { | ||
result = result * x; | ||
@@ -169,10 +160,15 @@ result = result % n; | ||
return result; | ||
}; | ||
} | ||
module.exports = { | ||
abs: abs, | ||
gcd: gcd, | ||
lcm: lcm, | ||
modInv: modInv, | ||
modPow: modPow | ||
}; | ||
/** | ||
* 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 | ||
*/ | ||
export function toZn(a, n) { | ||
n = BigInt(n); | ||
a = BigInt(a) % n; | ||
return (a < 0) ? a + n : a; | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
32894
12
769
206