final touchs
This commit is contained in:
parent
944deb4ebd
commit
f500432c5b
|
@ -2,11 +2,15 @@
|
||||||
"env": {
|
"env": {
|
||||||
"node": true,
|
"node": true,
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"mocha": true,
|
"mocha": true
|
||||||
"es6": true
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2017,
|
||||||
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
"extends": "eslint:recommended",
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"no-console": 0,
|
||||||
"indent": [
|
"indent": [
|
||||||
"error",
|
"error",
|
||||||
4
|
4
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
const rollup = require('rollup');
|
||||||
|
const commonjs = require('rollup-plugin-commonjs');
|
||||||
|
const minify = require('rollup-plugin-babel-minify');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const pkgJson = require('../package.json');
|
||||||
|
|
||||||
|
|
||||||
|
const buildOptions = [
|
||||||
|
{ // Browser
|
||||||
|
input: {
|
||||||
|
input: path.join(__dirname, '..', 'src', 'main.js'),
|
||||||
|
plugins: [
|
||||||
|
commonjs()
|
||||||
|
],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.browser.mod.js`),
|
||||||
|
format: 'esm'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ // Browser minified
|
||||||
|
input: {
|
||||||
|
input: path.join(__dirname, '..', 'src', 'main.js'),
|
||||||
|
plugins: [
|
||||||
|
commonjs(),
|
||||||
|
minify({
|
||||||
|
'comments': false
|
||||||
|
})
|
||||||
|
],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.browser.mod.min.js`),
|
||||||
|
format: 'esm'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ // Node
|
||||||
|
input: {
|
||||||
|
input: path.join(__dirname, '..', 'src', 'main.js'),
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.node.js`),
|
||||||
|
format: 'cjs'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const options of buildOptions) {
|
||||||
|
build(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* --- HELPLER FUNCTIONS --- */
|
||||||
|
|
||||||
|
async function build(options) {
|
||||||
|
// create a bundle
|
||||||
|
const bundle = await rollup.rollup(options.input);
|
||||||
|
|
||||||
|
// generate code
|
||||||
|
await bundle.generate(options.output);
|
||||||
|
|
||||||
|
// or write the bundle to disk
|
||||||
|
await bundle.write(options.output);
|
||||||
|
|
||||||
|
// copy the latest build as pkg_name-latest
|
||||||
|
fs.copyFileSync(
|
||||||
|
options.output.file,
|
||||||
|
options.output.file.replace(`${pkgJson.name}-${pkgJson.version}.`, `${pkgJson.name}-latest.`)
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
const abs = function (a) {
|
||||||
|
a = BigInt(a);
|
||||||
|
return (a >= BigInt(0)) ? a : -a;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
const gcd = function (a, b) {
|
||||||
|
a = abs(a);
|
||||||
|
b = abs(b);
|
||||||
|
let shift = BigInt(0);
|
||||||
|
while (!((a | b) & BigInt(1))) {
|
||||||
|
a >>= BigInt(1);
|
||||||
|
b >>= BigInt(1);
|
||||||
|
shift++;
|
||||||
|
}
|
||||||
|
while (!(a & BigInt(1))) a >>= BigInt(1);
|
||||||
|
do {
|
||||||
|
while (!(b & BigInt(1))) b >>= BigInt(1);
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
const lcm = function (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.
|
||||||
|
*
|
||||||
|
* @param {number|bigint} a The number to find an inverse for
|
||||||
|
* @param {number|bigint} n The modulo
|
||||||
|
*
|
||||||
|
* @returns {bigint} the inverse modulo n
|
||||||
|
*/
|
||||||
|
const modInv = function (a, n) {
|
||||||
|
let egcd = eGcd(a, n);
|
||||||
|
if (egcd.b !== BigInt(1)) {
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
const modPow = function (a, b, n) {
|
||||||
|
// See Knuth, volume 2, section 4.6.3.
|
||||||
|
n = BigInt(n);
|
||||||
|
a = toZn(a, n);
|
||||||
|
b = BigInt(b);
|
||||||
|
if (b < BigInt(0)) {
|
||||||
|
return modInv(modPow(a, abs(b), n), n);
|
||||||
|
}
|
||||||
|
let result = BigInt(1);
|
||||||
|
let x = a;
|
||||||
|
while (b > 0) {
|
||||||
|
var leastSignificantBit = b % BigInt(2);
|
||||||
|
b = b / BigInt(2);
|
||||||
|
if (leastSignificantBit == BigInt(1)) {
|
||||||
|
result = result * x;
|
||||||
|
result = result % n;
|
||||||
|
}
|
||||||
|
x = x * x;
|
||||||
|
x = x % 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;
|
||||||
|
|
||||||
|
export default main;
|
||||||
|
export { main_1 as abs, main_2 as gcd, main_3 as lcm, main_4 as modInv, main_5 as modPow };
|
|
@ -0,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};
|
|
@ -0,0 +1,169 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
const abs = function (a) {
|
||||||
|
a = BigInt(a);
|
||||||
|
return (a >= BigInt(0)) ? a : -a;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
const gcd = function (a, b) {
|
||||||
|
a = abs(a);
|
||||||
|
b = abs(b);
|
||||||
|
let shift = BigInt(0);
|
||||||
|
while (!((a | b) & BigInt(1))) {
|
||||||
|
a >>= BigInt(1);
|
||||||
|
b >>= BigInt(1);
|
||||||
|
shift++;
|
||||||
|
}
|
||||||
|
while (!(a & BigInt(1))) a >>= BigInt(1);
|
||||||
|
do {
|
||||||
|
while (!(b & BigInt(1))) b >>= BigInt(1);
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
const lcm = function (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.
|
||||||
|
*
|
||||||
|
* @param {number|bigint} a The number to find an inverse for
|
||||||
|
* @param {number|bigint} n The modulo
|
||||||
|
*
|
||||||
|
* @returns {bigint} the inverse modulo n
|
||||||
|
*/
|
||||||
|
const modInv = function (a, n) {
|
||||||
|
let egcd = eGcd(a, n);
|
||||||
|
if (egcd.b !== BigInt(1)) {
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
const modPow = function (a, b, n) {
|
||||||
|
// See Knuth, volume 2, section 4.6.3.
|
||||||
|
n = BigInt(n);
|
||||||
|
a = toZn(a, n);
|
||||||
|
b = BigInt(b);
|
||||||
|
if (b < BigInt(0)) {
|
||||||
|
return modInv(modPow(a, abs(b), n), n);
|
||||||
|
}
|
||||||
|
let result = BigInt(1);
|
||||||
|
let x = a;
|
||||||
|
while (b > 0) {
|
||||||
|
var leastSignificantBit = b % BigInt(2);
|
||||||
|
b = b / BigInt(2);
|
||||||
|
if (leastSignificantBit == BigInt(1)) {
|
||||||
|
result = result * x;
|
||||||
|
result = result % n;
|
||||||
|
}
|
||||||
|
x = x * x;
|
||||||
|
x = x % n;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
abs: abs,
|
||||||
|
gcd: gcd,
|
||||||
|
lcm: lcm,
|
||||||
|
modInv: modInv,
|
||||||
|
modPow: modPow
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
|
@ -18,14 +18,23 @@
|
||||||
"url": "https://github.com/juanelas"
|
"url": "https://github.com/juanelas"
|
||||||
},
|
},
|
||||||
"repository": "github:juanelas/bigint-mod-arith",
|
"repository": "github:juanelas/bigint-mod-arith",
|
||||||
"main": "./src/main.js",
|
"main": "./dist/bigint-mod-arith-latest.node.js",
|
||||||
|
"browser": "./dist/bigint-mod-arith-latest.browser.mod.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
"build": "./build",
|
||||||
|
"dist": "./dist",
|
||||||
"src": "./src"
|
"src": "./src"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"docs:build": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md"
|
"docs:build": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md",
|
||||||
|
"build": "node build/build.rollup.js",
|
||||||
|
"postinstall": "npm run build",
|
||||||
|
"prepublishOnly": "npm run build && npm run docs:build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jsdoc-to-markdown": "^4.0.1"
|
"jsdoc-to-markdown": "^4.0.1",
|
||||||
|
"rollup": "^1.9.0",
|
||||||
|
"rollup-plugin-babel-minify": "^8.0.0",
|
||||||
|
"rollup-plugin-commonjs": "^9.3.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue