modpow with crt; crt; modAdd; modMultiply
This commit is contained in:
parent
80793b35bb
commit
1375c85bb5
|
@ -86,31 +86,31 @@ jobs:
|
|||
# VARIABLE1: ${{ secrets.VARIABLE1 }}
|
||||
# VARIABLE2: ${{ secrets.VARIABLE2 }}
|
||||
|
||||
publish:
|
||||
needs: [nodetests, browsertests]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Git checkout
|
||||
uses: actions/checkout@v3
|
||||
# publish:
|
||||
# needs: [nodetests, browsertests]
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Git checkout
|
||||
# uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js, NPM and Yarn
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18.x"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
# - name: Install Node.js, NPM and Yarn
|
||||
# uses: actions/setup-node@v3
|
||||
# with:
|
||||
# node-version: "18.x"
|
||||
# registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: install
|
||||
run: npm ci
|
||||
# # - name: install
|
||||
# # run: npm ci
|
||||
|
||||
- name: coverage
|
||||
run: npm run coverage
|
||||
# # - name: coverage
|
||||
# # run: npm run coverage
|
||||
|
||||
- name: send report to coveralls.io
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# # - name: send report to coveralls.io
|
||||
# # uses: coverallsapp/github-action@master
|
||||
# # with:
|
||||
# # github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: NPM publish
|
||||
run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
# - name: NPM publish
|
||||
# run: npm publish --access public
|
||||
# env:
|
||||
# NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@ -8,10 +8,10 @@ import replace from '@rollup/plugin-replace'
|
|||
import terser from '@rollup/plugin-terser'
|
||||
import rollupPluginTs from '@rollup/plugin-typescript'
|
||||
import { existsSync, readFileSync } from 'fs'
|
||||
import { dirname, join } from 'path'
|
||||
import { builtinModules } from 'module'
|
||||
import { join } from 'path'
|
||||
import dts from 'rollup-plugin-dts'
|
||||
import { compile } from './rollup-plugin-dts.js'
|
||||
import { builtinModules } from 'module'
|
||||
|
||||
import * as url from 'url'
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
@ -45,7 +45,7 @@ if (existsSync(input) !== true) throw new Error('The entry point should be index
|
|||
const tsPluginOptions = {
|
||||
tsconfig: tsConfigPath,
|
||||
outDir: undefined,
|
||||
include: ['src/ts/**/*', 'build/typings/is-browser.d.ts'],
|
||||
include: ['src/ts/**/*', 'build/typings/**/*.d.ts'],
|
||||
exclude: ['src/**/*.spec.ts']
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,9 @@ export default [
|
|||
plugins: [
|
||||
replace({
|
||||
IS_BROWSER: true,
|
||||
environment: 'browser',
|
||||
_MODULE_TYPE: "'ESM'",
|
||||
_NPM_PKG_VERSION: `'${process.env.npm_package_version}'` ?? "'0.0.1'",
|
||||
preventAssignment: true
|
||||
}),
|
||||
rollupPluginTs(tsPluginOptions),
|
||||
|
@ -142,7 +144,9 @@ export default [
|
|||
plugins: [
|
||||
replace({
|
||||
IS_BROWSER: true,
|
||||
environment: 'browser',
|
||||
_MODULE_TYPE: "'BUNDLE'",
|
||||
_NPM_PKG_VERSION: `'${process.env.npm_package_version}'` ?? "'0.0.1'",
|
||||
preventAssignment: true
|
||||
}),
|
||||
rollupPluginTs({
|
||||
|
@ -162,20 +166,17 @@ export default [
|
|||
...sourcemapOutputOptions,
|
||||
format: 'cjs',
|
||||
exports: 'auto',
|
||||
plugins: [
|
||||
terser()
|
||||
]
|
||||
interop: 'auto',
|
||||
dynamicImportInCjs: false,
|
||||
plugins: [terser()]
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
replace({
|
||||
'await import(': 'require(',
|
||||
delimiters: ['', ''],
|
||||
preventAssignment: true
|
||||
}),
|
||||
replace({
|
||||
IS_BROWSER: false,
|
||||
environment: 'nodejs',
|
||||
_MODULE_TYPE: "'CJS'",
|
||||
_NPM_PKG_VERSION: `'${process.env.npm_package_version}'` ?? "'0.0.1'",
|
||||
preventAssignment: true
|
||||
}),
|
||||
rollupPluginTs(tsPluginOptions),
|
||||
|
@ -197,23 +198,24 @@ export default [
|
|||
file: join(rootDir, pkgJson.exports['.'].node.import.default),
|
||||
...sourcemapOutputOptions,
|
||||
format: 'es',
|
||||
plugins: [
|
||||
terser()
|
||||
]
|
||||
plugins: [terser()]
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
replace({
|
||||
IS_BROWSER: false,
|
||||
environment: 'nodejs',
|
||||
_MODULE_TYPE: "'ESM'",
|
||||
__filename: `'${pkgJson.exports['.'].node.import.default}'`,
|
||||
__dirname: `'${dirname(pkgJson.exports['.'].node.import.default)}'`,
|
||||
_NPM_PKG_VERSION: `'${process.env.npm_package_version}'` ?? "'0.0.1'",
|
||||
__filename: 'fileURLToPath(import.meta.url)',
|
||||
__dirname: 'fileURLToPath(new URL(\'.\', import.meta.url))',
|
||||
preventAssignment: true
|
||||
}),
|
||||
rollupPluginTs(tsPluginOptions),
|
||||
compileDts(tmpDeclarationsDir),
|
||||
inject({
|
||||
crypto: ['crypto', 'webcrypto']
|
||||
crypto: ['crypto', 'webcrypto'],
|
||||
fileURLToPath: ['url', 'fileURLToPath']
|
||||
}),
|
||||
commonjs({ extensions: ['.js', '.cjs', '.jsx', '.cjsx'] }),
|
||||
json(),
|
||||
|
|
|
@ -61,7 +61,7 @@ const browserTests = async (
|
|||
await watchDog.catch(async (reason) => {
|
||||
console.error(reason)
|
||||
})
|
||||
if (puppeteerOptions.headless === true) {
|
||||
if (puppeteerOptions.headless === 'new') {
|
||||
await close()
|
||||
}
|
||||
}).catch(async (reason) => {
|
||||
|
@ -102,9 +102,9 @@ const opts = {
|
|||
// puppeteer options
|
||||
puppeteerOptions: {
|
||||
headless: false,
|
||||
devtools: true
|
||||
devtools: true,
|
||||
// slowMo: 100,
|
||||
// timeout: 10000
|
||||
timeout: 0
|
||||
},
|
||||
logWarnings: false, // log warnings in Node console (usually not needed)
|
||||
keepServerRunning: false, // keep server running until manually closed with ctrl-c. In combination with puppeteerOptions.headless (or just connecting any browser to the test page) allows debugging in browser
|
||||
|
@ -113,7 +113,7 @@ const opts = {
|
|||
|
||||
const args = process.argv.slice(2)
|
||||
if (args[0] === 'headless') {
|
||||
opts.puppeteerOptions.headless = true
|
||||
opts.puppeteerOptions.headless = 'new'
|
||||
args.shift()
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ const tsBundleOptions = {
|
|||
tsconfig: path.join(rootDir, 'tsconfig.json'),
|
||||
outDir: undefined, // ignore outDir in tsconfig.json
|
||||
sourceMap: false
|
||||
// include: ['build/typings/is-browser.d.ts']
|
||||
// include: ['src/ts/**/*', 'build/typings/**/*.d.ts']
|
||||
}
|
||||
|
||||
async function buildTests (testFiles) {
|
||||
|
@ -63,6 +63,7 @@ async function buildTests (testFiles) {
|
|||
replace({
|
||||
IS_BROWSER: true,
|
||||
_MODULE_TYPE: "'ESM'",
|
||||
_NPM_PKG_VERSION: `'${process.env.npm_package_version}'` ?? "'0.0.1'",
|
||||
preventAssignment: true
|
||||
}),
|
||||
typescriptPlugin(tsBundleOptions),
|
||||
|
@ -202,7 +203,7 @@ function _getEnvVarsReplacements (testsCode) {
|
|||
}
|
||||
}
|
||||
if (missingEnvVars.length > 0) {
|
||||
console.warn('The folloinwg environment variables are missing in your .env file and will be replaced with "undefined": ' + [...(new Set(missingEnvVars)).values()].join(', '))
|
||||
console.warn('The following environment variables are missing in your .env file and will be replaced with "undefined": ' + [...(new Set(missingEnvVars)).values()].join(', '))
|
||||
}
|
||||
return replacements
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
declare const IS_BROWSER: boolean
|
||||
declare const _MODULE_TYPE: string
|
|
@ -45,6 +45,41 @@ function eGcd(a, b) {
|
|||
};
|
||||
}
|
||||
|
||||
function toZn(a, n) {
|
||||
if (typeof a === 'number')
|
||||
a = BigInt(a);
|
||||
if (typeof n === 'number')
|
||||
n = BigInt(n);
|
||||
if (n <= 0n) {
|
||||
throw new RangeError('n must be > 0');
|
||||
}
|
||||
const aZn = a % n;
|
||||
return (aZn < 0n) ? aZn + n : aZn;
|
||||
}
|
||||
|
||||
function modInv(a, n) {
|
||||
const egcd = eGcd(toZn(a, n), n);
|
||||
if (egcd.g !== 1n) {
|
||||
throw new RangeError(`${a.toString()} does not have inverse modulo ${n.toString()}`);
|
||||
}
|
||||
else {
|
||||
return toZn(egcd.x, n);
|
||||
}
|
||||
}
|
||||
|
||||
function crt(remainders, modulos, modulo) {
|
||||
if (remainders.length !== modulos.length) {
|
||||
throw new RangeError('The remainders and modulos arrays should have the same length');
|
||||
}
|
||||
const product = modulo ?? modulos.reduce((acc, val) => acc * val, 1n);
|
||||
return modulos.reduce((sum, mod, index) => {
|
||||
const partialProduct = product / mod;
|
||||
const inverse = modInv(partialProduct, mod);
|
||||
const toAdd = ((partialProduct * inverse) % product * remainders[index]) % product;
|
||||
return toZn(sum + toAdd, product);
|
||||
}, 0n);
|
||||
}
|
||||
|
||||
function gcd(a, b) {
|
||||
let aAbs = (typeof a === 'number') ? BigInt(abs(a)) : abs(a);
|
||||
let bAbs = (typeof b === 'number') ? BigInt(abs(b)) : abs(b);
|
||||
|
@ -93,29 +128,25 @@ function min(a, b) {
|
|||
return (a >= b) ? b : a;
|
||||
}
|
||||
|
||||
function toZn(a, n) {
|
||||
if (typeof a === 'number')
|
||||
a = BigInt(a);
|
||||
if (typeof n === 'number')
|
||||
n = BigInt(n);
|
||||
if (n <= 0n) {
|
||||
throw new RangeError('n must be > 0');
|
||||
}
|
||||
const aZn = a % n;
|
||||
return (aZn < 0n) ? aZn + n : aZn;
|
||||
function modAdd(addends, n) {
|
||||
const mod = BigInt(n);
|
||||
const as = addends.map(a => BigInt(a) % mod);
|
||||
return toZn(as.reduce((sum, a) => sum + a % mod, 0n), mod);
|
||||
}
|
||||
|
||||
function modInv(a, n) {
|
||||
const egcd = eGcd(toZn(a, n), n);
|
||||
if (egcd.g !== 1n) {
|
||||
throw new RangeError(`${a.toString()} does not have inverse modulo ${n.toString()}`);
|
||||
}
|
||||
else {
|
||||
return toZn(egcd.x, n);
|
||||
}
|
||||
function modMultiply(factors, n) {
|
||||
const mod = BigInt(n);
|
||||
const as = factors.map(a => BigInt(a) % mod);
|
||||
return toZn(as.reduce((prod, a) => prod * a % mod, 1n), mod);
|
||||
}
|
||||
|
||||
function modPow(b, e, n) {
|
||||
function phi(primeFactorization) {
|
||||
return primeFactorization.map(v => (v[0] ** (v[1] - 1n)) * (v[0] - 1n)).reduce((prev, curr) => {
|
||||
return curr * prev;
|
||||
}, 1n);
|
||||
}
|
||||
|
||||
function modPow(b, e, n, primeFactorization) {
|
||||
if (typeof b === 'number')
|
||||
b = BigInt(b);
|
||||
if (typeof e === 'number')
|
||||
|
@ -130,7 +161,10 @@ function modPow(b, e, n) {
|
|||
}
|
||||
b = toZn(b, n);
|
||||
if (e < 0n) {
|
||||
return modInv(modPow(b, abs(e), n), n);
|
||||
return modInv(modPow(b, abs(e), n, primeFactorization), n);
|
||||
}
|
||||
if (primeFactorization !== undefined) {
|
||||
return modPowWithFactorization(b, e, n, primePowerArguments(primeFactorization));
|
||||
}
|
||||
let r = 1n;
|
||||
while (e > 0) {
|
||||
|
@ -142,5 +176,35 @@ function modPow(b, e, n) {
|
|||
}
|
||||
return r;
|
||||
}
|
||||
function primePowerArguments(primeFactors) {
|
||||
const primePowers = {};
|
||||
primeFactors.forEach((primeFactor) => {
|
||||
if (typeof primeFactor === 'bigint' || typeof primeFactor === 'number') {
|
||||
const key = String(primeFactor);
|
||||
if (primePowers[key] === undefined) {
|
||||
primePowers[key] = { p: BigInt(primeFactor), k: 1n };
|
||||
}
|
||||
else {
|
||||
primePowers[key].k += 1n;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const key = String(primeFactor[0]);
|
||||
if (primePowers[key] === undefined) {
|
||||
primePowers[key] = { p: BigInt(primeFactor[0]), k: BigInt(primeFactor[1]) };
|
||||
}
|
||||
else {
|
||||
primePowers[key].k += BigInt(primeFactor[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
return Object.values(primePowers).map(val => [val.p, val.k]);
|
||||
}
|
||||
function modPowWithFactorization(b, e, n, primeFactorization) {
|
||||
const mods = primeFactorization.map(v => v[0] ** v[1]);
|
||||
const phis = primeFactorization.map(v => phi([v]));
|
||||
const remainders = phis.map((phi, i) => modPow(b, e % phi, mods[i]));
|
||||
return crt(remainders, mods, n);
|
||||
}
|
||||
|
||||
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn };
|
||||
export { abs, bitLength, crt, eGcd, gcd, lcm, max, min, modAdd, modInv, modMultiply, modPow, phi, toZn };
|
||||
|
|
|
@ -1 +1 @@
|
|||
function n(n){return n>=0?n:-n}function t(n){if("number"==typeof n&&(n=BigInt(n)),1n===n)return 1;let t=1;do{t++}while((n>>=1n)>1n);return t}function r(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),n<=0n||t<=0n)throw new RangeError("a and b MUST be > 0");let r=0n,e=1n,o=1n,u=0n;for(;0n!==n;){const i=t/n,f=t%n,g=r-o*i,b=e-u*i;t=n,n=f,r=o,e=u,o=g,u=b}return{g:t,x:r,y:e}}function e(t,r){let e="number"==typeof t?BigInt(n(t)):n(t),o="number"==typeof r?BigInt(n(r)):n(r);if(0n===e)return o;if(0n===o)return e;let u=0n;for(;0n===(1n&(e|o));)e>>=1n,o>>=1n,u++;for(;0n===(1n&e);)e>>=1n;do{for(;0n===(1n&o);)o>>=1n;if(e>o){const n=e;e=o,o=n}o-=e}while(0n!==o);return e<<u}function o(t,r){return"number"==typeof t&&(t=BigInt(t)),"number"==typeof r&&(r=BigInt(r)),0n===t&&0n===r?BigInt(0):n(t/e(t,r)*r)}function u(n,t){return n>=t?n:t}function i(n,t){return n>=t?t:n}function f(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),t<=0n)throw new RangeError("n must be > 0");const r=n%t;return r<0n?r+t:r}function g(n,t){const e=r(f(n,t),t);if(1n!==e.g)throw new RangeError(`${n.toString()} does not have inverse modulo ${t.toString()}`);return f(e.x,t)}function b(t,r,e){if("number"==typeof t&&(t=BigInt(t)),"number"==typeof r&&(r=BigInt(r)),"number"==typeof e&&(e=BigInt(e)),e<=0n)throw new RangeError("n must be > 0");if(1n===e)return 0n;if(t=f(t,e),r<0n)return g(b(t,n(r),e),e);let o=1n;for(;r>0;)r%2n===1n&&(o=o*t%e),r/=2n,t=t**2n%e;return o}export{n as abs,t as bitLength,r as eGcd,e as gcd,o as lcm,u as max,i as min,g as modInv,b as modPow,f as toZn};
|
||||
function n(n){return n>=0?n:-n}function t(n){if("number"==typeof n&&(n=BigInt(n)),1n===n)return 1;let t=1;do{t++}while((n>>=1n)>1n);return t}function r(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),n<=0n||t<=0n)throw new RangeError("a and b MUST be > 0");let r=0n,e=1n,o=1n,i=0n;for(;0n!==n;){const u=t/n,f=t%n,g=r-o*u,c=e-i*u;t=n,n=f,r=o,e=i,o=g,i=c}return{g:t,x:r,y:e}}function e(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),t<=0n)throw new RangeError("n must be > 0");const r=n%t;return r<0n?r+t:r}function o(n,t){const o=r(e(n,t),t);if(1n!==o.g)throw new RangeError(`${n.toString()} does not have inverse modulo ${t.toString()}`);return e(o.x,t)}function i(n,t,r){if(n.length!==t.length)throw new RangeError("The remainders and modulos arrays should have the same length");const i=r??t.reduce(((n,t)=>n*t),1n);return t.reduce(((t,r,u)=>{const f=i/r;return e(t+f*o(f,r)%i*n[u]%i,i)}),0n)}function u(t,r){let e="number"==typeof t?BigInt(n(t)):n(t),o="number"==typeof r?BigInt(n(r)):n(r);if(0n===e)return o;if(0n===o)return e;let i=0n;for(;0n===(1n&(e|o));)e>>=1n,o>>=1n,i++;for(;0n===(1n&e);)e>>=1n;do{for(;0n===(1n&o);)o>>=1n;if(e>o){const n=e;e=o,o=n}o-=e}while(0n!==o);return e<<i}function f(t,r){return"number"==typeof t&&(t=BigInt(t)),"number"==typeof r&&(r=BigInt(r)),0n===t&&0n===r?BigInt(0):n(t/u(t,r)*r)}function g(n,t){return n>=t?n:t}function c(n,t){return n>=t?t:n}function m(n,t){const r=BigInt(t);return e(n.map((n=>BigInt(n)%r)).reduce(((n,t)=>n+t%r),0n),r)}function p(n,t){const r=BigInt(t);return e(n.map((n=>BigInt(n)%r)).reduce(((n,t)=>n*t%r),1n),r)}function a(n){return n.map((n=>n[0]**(n[1]-1n)*(n[0]-1n))).reduce(((n,t)=>t*n),1n)}function s(t,r,u,f){if("number"==typeof t&&(t=BigInt(t)),"number"==typeof r&&(r=BigInt(r)),"number"==typeof u&&(u=BigInt(u)),u<=0n)throw new RangeError("n must be > 0");if(1n===u)return 0n;if(t=e(t,u),r<0n)return o(s(t,n(r),u,f),u);if(void 0!==f)return function(n,t,r,e){const o=e.map((n=>n[0]**n[1])),u=e.map((n=>a([n]))),f=u.map(((r,e)=>s(n,t%r,o[e])));return i(f,o,r)}(t,r,u,function(n){const t={};return n.forEach((n=>{if("bigint"==typeof n||"number"==typeof n){const r=String(n);void 0===t[r]?t[r]={p:BigInt(n),k:1n}:t[r].k+=1n}else{const r=String(n[0]);void 0===t[r]?t[r]={p:BigInt(n[0]),k:BigInt(n[1])}:t[r].k+=BigInt(n[1])}})),Object.values(t).map((n=>[n.p,n.k]))}(f));let g=1n;for(;r>0;)r%2n===1n&&(g=g*t%u),r/=2n,t=t**2n%u;return g}export{n as abs,t as bitLength,i as crt,r as eGcd,u as gcd,f as lcm,g as max,c as min,m as modAdd,o as modInv,p as modMultiply,s as modPow,a as phi,e as toZn};
|
||||
|
|
|
@ -1 +1 @@
|
|||
var bigintModArith=function(n){"use strict";function t(n){return n>=0?n:-n}function r(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),n<=0n||t<=0n)throw new RangeError("a and b MUST be > 0");let r=0n,e=1n,o=1n,i=0n;for(;0n!==n;){const u=t/n,f=t%n,g=r-o*u,m=e-i*u;t=n,n=f,r=o,e=i,o=g,i=m}return{g:t,x:r,y:e}}function e(n,r){let e="number"==typeof n?BigInt(t(n)):t(n),o="number"==typeof r?BigInt(t(r)):t(r);if(0n===e)return o;if(0n===o)return e;let i=0n;for(;0n===(1n&(e|o));)e>>=1n,o>>=1n,i++;for(;0n===(1n&e);)e>>=1n;do{for(;0n===(1n&o);)o>>=1n;if(e>o){const n=e;e=o,o=n}o-=e}while(0n!==o);return e<<i}function o(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),t<=0n)throw new RangeError("n must be > 0");const r=n%t;return r<0n?r+t:r}function i(n,t){const e=r(o(n,t),t);if(1n!==e.g)throw new RangeError(`${n.toString()} does not have inverse modulo ${t.toString()}`);return o(e.x,t)}return n.abs=t,n.bitLength=function(n){if("number"==typeof n&&(n=BigInt(n)),1n===n)return 1;let t=1;do{t++}while((n>>=1n)>1n);return t},n.eGcd=r,n.gcd=e,n.lcm=function(n,r){return"number"==typeof n&&(n=BigInt(n)),"number"==typeof r&&(r=BigInt(r)),0n===n&&0n===r?BigInt(0):t(n/e(n,r)*r)},n.max=function(n,t){return n>=t?n:t},n.min=function(n,t){return n>=t?t:n},n.modInv=i,n.modPow=function n(r,e,u){if("number"==typeof r&&(r=BigInt(r)),"number"==typeof e&&(e=BigInt(e)),"number"==typeof u&&(u=BigInt(u)),u<=0n)throw new RangeError("n must be > 0");if(1n===u)return 0n;if(r=o(r,u),e<0n)return i(n(r,t(e),u),u);let f=1n;for(;e>0;)e%2n===1n&&(f=f*r%u),e/=2n,r=r**2n%u;return f},n.toZn=o,n}({});
|
||||
var bigintModArith=function(n){"use strict";function t(n){return n>=0?n:-n}function r(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),n<=0n||t<=0n)throw new RangeError("a and b MUST be > 0");let r=0n,e=1n,o=1n,i=0n;for(;0n!==n;){const u=t/n,f=t%n,c=r-o*u,g=e-i*u;t=n,n=f,r=o,e=i,o=c,i=g}return{g:t,x:r,y:e}}function e(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),t<=0n)throw new RangeError("n must be > 0");const r=n%t;return r<0n?r+t:r}function o(n,t){const o=r(e(n,t),t);if(1n!==o.g)throw new RangeError(`${n.toString()} does not have inverse modulo ${t.toString()}`);return e(o.x,t)}function i(n,t,r){if(n.length!==t.length)throw new RangeError("The remainders and modulos arrays should have the same length");const i=r??t.reduce(((n,t)=>n*t),1n);return t.reduce(((t,r,u)=>{const f=i/r;return e(t+f*o(f,r)%i*n[u]%i,i)}),0n)}function u(n,r){let e="number"==typeof n?BigInt(t(n)):t(n),o="number"==typeof r?BigInt(t(r)):t(r);if(0n===e)return o;if(0n===o)return e;let i=0n;for(;0n===(1n&(e|o));)e>>=1n,o>>=1n,i++;for(;0n===(1n&e);)e>>=1n;do{for(;0n===(1n&o);)o>>=1n;if(e>o){const n=e;e=o,o=n}o-=e}while(0n!==o);return e<<i}function f(n){return n.map((n=>n[0]**(n[1]-1n)*(n[0]-1n))).reduce(((n,t)=>t*n),1n)}function c(n,r,u,g){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof r&&(r=BigInt(r)),"number"==typeof u&&(u=BigInt(u)),u<=0n)throw new RangeError("n must be > 0");if(1n===u)return 0n;if(n=e(n,u),r<0n)return o(c(n,t(r),u,g),u);if(void 0!==g)return function(n,t,r,e){const o=e.map((n=>n[0]**n[1])),u=e.map((n=>f([n]))),g=u.map(((r,e)=>c(n,t%r,o[e])));return i(g,o,r)}(n,r,u,function(n){const t={};return n.forEach((n=>{if("bigint"==typeof n||"number"==typeof n){const r=String(n);void 0===t[r]?t[r]={p:BigInt(n),k:1n}:t[r].k+=1n}else{const r=String(n[0]);void 0===t[r]?t[r]={p:BigInt(n[0]),k:BigInt(n[1])}:t[r].k+=BigInt(n[1])}})),Object.values(t).map((n=>[n.p,n.k]))}(g));let m=1n;for(;r>0;)r%2n===1n&&(m=m*n%u),r/=2n,n=n**2n%u;return m}return n.abs=t,n.bitLength=function(n){if("number"==typeof n&&(n=BigInt(n)),1n===n)return 1;let t=1;do{t++}while((n>>=1n)>1n);return t},n.crt=i,n.eGcd=r,n.gcd=u,n.lcm=function(n,r){return"number"==typeof n&&(n=BigInt(n)),"number"==typeof r&&(r=BigInt(r)),0n===n&&0n===r?BigInt(0):t(n/u(n,r)*r)},n.max=function(n,t){return n>=t?n:t},n.min=function(n,t){return n>=t?t:n},n.modAdd=function(n,t){const r=BigInt(t);return e(n.map((n=>BigInt(n)%r)).reduce(((n,t)=>n+t%r),0n),r)},n.modInv=o,n.modMultiply=function(n,t){const r=BigInt(t);return e(n.map((n=>BigInt(n)%r)).reduce(((n,t)=>n*t%r),1n),r)},n.modPow=c,n.phi=f,n.toZn=e,n}({});
|
||||
|
|
|
@ -1 +1 @@
|
|||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n="undefined"!=typeof globalThis?globalThis:n||self).bigintModArith={})}(this,(function(n){"use strict";function t(n){return n>=0?n:-n}function e(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),n<=0n||t<=0n)throw new RangeError("a and b MUST be > 0");let e=0n,r=1n,o=1n,i=0n;for(;0n!==n;){const f=t/n,u=t%n,g=e-o*f,b=r-i*f;t=n,n=u,e=o,r=i,o=g,i=b}return{g:t,x:e,y:r}}function r(n,e){let r="number"==typeof n?BigInt(t(n)):t(n),o="number"==typeof e?BigInt(t(e)):t(e);if(0n===r)return o;if(0n===o)return r;let i=0n;for(;0n===(1n&(r|o));)r>>=1n,o>>=1n,i++;for(;0n===(1n&r);)r>>=1n;do{for(;0n===(1n&o);)o>>=1n;if(r>o){const n=r;r=o,o=n}o-=r}while(0n!==o);return r<<i}function o(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),t<=0n)throw new RangeError("n must be > 0");const e=n%t;return e<0n?e+t:e}function i(n,t){const r=e(o(n,t),t);if(1n!==r.g)throw new RangeError(`${n.toString()} does not have inverse modulo ${t.toString()}`);return o(r.x,t)}n.abs=t,n.bitLength=function(n){if("number"==typeof n&&(n=BigInt(n)),1n===n)return 1;let t=1;do{t++}while((n>>=1n)>1n);return t},n.eGcd=e,n.gcd=r,n.lcm=function(n,e){return"number"==typeof n&&(n=BigInt(n)),"number"==typeof e&&(e=BigInt(e)),0n===n&&0n===e?BigInt(0):t(n/r(n,e)*e)},n.max=function(n,t){return n>=t?n:t},n.min=function(n,t){return n>=t?t:n},n.modInv=i,n.modPow=function n(e,r,f){if("number"==typeof e&&(e=BigInt(e)),"number"==typeof r&&(r=BigInt(r)),"number"==typeof f&&(f=BigInt(f)),f<=0n)throw new RangeError("n must be > 0");if(1n===f)return 0n;if(e=o(e,f),r<0n)return i(n(e,t(r),f),f);let u=1n;for(;r>0;)r%2n===1n&&(u=u*e%f),r/=2n,e=e**2n%f;return u},n.toZn=o}));
|
||||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n="undefined"!=typeof globalThis?globalThis:n||self).bigintModArith={})}(this,(function(n){"use strict";function t(n){return n>=0?n:-n}function e(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),n<=0n||t<=0n)throw new RangeError("a and b MUST be > 0");let e=0n,r=1n,o=1n,i=0n;for(;0n!==n;){const u=t/n,f=t%n,c=e-o*u,g=r-i*u;t=n,n=f,e=o,r=i,o=c,i=g}return{g:t,x:e,y:r}}function r(n,t){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof t&&(t=BigInt(t)),t<=0n)throw new RangeError("n must be > 0");const e=n%t;return e<0n?e+t:e}function o(n,t){const o=e(r(n,t),t);if(1n!==o.g)throw new RangeError(`${n.toString()} does not have inverse modulo ${t.toString()}`);return r(o.x,t)}function i(n,t,e){if(n.length!==t.length)throw new RangeError("The remainders and modulos arrays should have the same length");const i=e??t.reduce(((n,t)=>n*t),1n);return t.reduce(((t,e,u)=>{const f=i/e;return r(t+f*o(f,e)%i*n[u]%i,i)}),0n)}function u(n,e){let r="number"==typeof n?BigInt(t(n)):t(n),o="number"==typeof e?BigInt(t(e)):t(e);if(0n===r)return o;if(0n===o)return r;let i=0n;for(;0n===(1n&(r|o));)r>>=1n,o>>=1n,i++;for(;0n===(1n&r);)r>>=1n;do{for(;0n===(1n&o);)o>>=1n;if(r>o){const n=r;r=o,o=n}o-=r}while(0n!==o);return r<<i}function f(n){return n.map((n=>n[0]**(n[1]-1n)*(n[0]-1n))).reduce(((n,t)=>t*n),1n)}function c(n,e,u,g){if("number"==typeof n&&(n=BigInt(n)),"number"==typeof e&&(e=BigInt(e)),"number"==typeof u&&(u=BigInt(u)),u<=0n)throw new RangeError("n must be > 0");if(1n===u)return 0n;if(n=r(n,u),e<0n)return o(c(n,t(e),u,g),u);if(void 0!==g)return function(n,t,e,r){const o=r.map((n=>n[0]**n[1])),u=r.map((n=>f([n]))),g=u.map(((e,r)=>c(n,t%e,o[r])));return i(g,o,e)}(n,e,u,function(n){const t={};return n.forEach((n=>{if("bigint"==typeof n||"number"==typeof n){const e=String(n);void 0===t[e]?t[e]={p:BigInt(n),k:1n}:t[e].k+=1n}else{const e=String(n[0]);void 0===t[e]?t[e]={p:BigInt(n[0]),k:BigInt(n[1])}:t[e].k+=BigInt(n[1])}})),Object.values(t).map((n=>[n.p,n.k]))}(g));let d=1n;for(;e>0;)e%2n===1n&&(d=d*n%u),e/=2n,n=n**2n%u;return d}n.abs=t,n.bitLength=function(n){if("number"==typeof n&&(n=BigInt(n)),1n===n)return 1;let t=1;do{t++}while((n>>=1n)>1n);return t},n.crt=i,n.eGcd=e,n.gcd=u,n.lcm=function(n,e){return"number"==typeof n&&(n=BigInt(n)),"number"==typeof e&&(e=BigInt(e)),0n===n&&0n===e?BigInt(0):t(n/u(n,e)*e)},n.max=function(n,t){return n>=t?n:t},n.min=function(n,t){return n>=t?t:n},n.modAdd=function(n,t){const e=BigInt(t);return r(n.map((n=>BigInt(n)%e)).reduce(((n,t)=>n+t%e),0n),e)},n.modInv=o,n.modMultiply=function(n,t){const e=BigInt(t);return r(n.map((n=>BigInt(n)%e)).reduce(((n,t)=>n*t%e),1n),e)},n.modPow=c,n.phi=f,n.toZn=r}));
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2,6 +2,8 @@ declare function abs(a: number | bigint): number | bigint;
|
|||
|
||||
declare function bitLength(a: number | bigint): number;
|
||||
|
||||
declare function crt(remainders: bigint[], modulos: bigint[], modulo?: bigint): bigint;
|
||||
|
||||
interface Egcd {
|
||||
g: bigint;
|
||||
x: bigint;
|
||||
|
@ -17,10 +19,19 @@ declare function max(a: number | bigint, b: number | bigint): number | bigint;
|
|||
|
||||
declare function min(a: number | bigint, b: number | bigint): number | bigint;
|
||||
|
||||
declare function modAdd(addends: Array<number | bigint>, n: number | bigint): bigint;
|
||||
|
||||
declare function modInv(a: number | bigint, n: number | bigint): bigint;
|
||||
|
||||
declare function modPow(b: number | bigint, e: number | bigint, n: number | bigint): bigint;
|
||||
declare function modMultiply(factors: Array<number | bigint>, n: number | bigint): bigint;
|
||||
|
||||
type PrimePower = [number | bigint, number | bigint];
|
||||
type PrimeFactor = number | bigint | PrimePower;
|
||||
declare function modPow(b: number | bigint, e: number | bigint, n: number | bigint, primeFactorization?: PrimeFactor[]): bigint;
|
||||
|
||||
type PrimeFactorization = Array<[bigint, bigint]>;
|
||||
declare function phi(primeFactorization: PrimeFactorization): bigint;
|
||||
|
||||
declare function toZn(a: number | bigint, n: number | bigint): bigint;
|
||||
|
||||
export { Egcd, abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn };
|
||||
export { Egcd, PrimeFactor, PrimeFactorization, PrimePower, abs, bitLength, crt, eGcd, gcd, lcm, max, min, modAdd, modInv, modMultiply, modPow, phi, toZn };
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
170
docs/API.md
170
docs/API.md
|
@ -8,19 +8,59 @@ Some common functions for modular arithmetic using native JS implementation of B
|
|||
|
||||
- [Egcd](interfaces/Egcd.md)
|
||||
|
||||
### Type Aliases
|
||||
|
||||
- [PrimeFactor](API.md#primefactor)
|
||||
- [PrimeFactorization](API.md#primefactorization)
|
||||
- [PrimePower](API.md#primepower)
|
||||
|
||||
### Functions
|
||||
|
||||
- [abs](API.md#abs)
|
||||
- [bitLength](API.md#bitlength)
|
||||
- [crt](API.md#crt)
|
||||
- [eGcd](API.md#egcd)
|
||||
- [gcd](API.md#gcd)
|
||||
- [lcm](API.md#lcm)
|
||||
- [max](API.md#max)
|
||||
- [min](API.md#min)
|
||||
- [modAdd](API.md#modadd)
|
||||
- [modInv](API.md#modinv)
|
||||
- [modMultiply](API.md#modmultiply)
|
||||
- [modPow](API.md#modpow)
|
||||
- [phi](API.md#phi)
|
||||
- [toZn](API.md#tozn)
|
||||
|
||||
## Type Aliases
|
||||
|
||||
### PrimeFactor
|
||||
|
||||
Ƭ **PrimeFactor**: `number` \| `bigint` \| [`PrimePower`](API.md#primepower)
|
||||
|
||||
#### Defined in
|
||||
|
||||
[modPow.ts:8](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/modPow.ts#L8)
|
||||
|
||||
___
|
||||
|
||||
### PrimeFactorization
|
||||
|
||||
Ƭ **PrimeFactorization**: [`bigint`, `bigint`][]
|
||||
|
||||
#### Defined in
|
||||
|
||||
phi.ts:1
|
||||
|
||||
___
|
||||
|
||||
### PrimePower
|
||||
|
||||
Ƭ **PrimePower**: [`number` \| `bigint`, `number` \| `bigint`]
|
||||
|
||||
#### Defined in
|
||||
|
||||
[modPow.ts:7](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/modPow.ts#L7)
|
||||
|
||||
## Functions
|
||||
|
||||
### abs
|
||||
|
@ -43,7 +83,7 @@ The absolute value of a
|
|||
|
||||
#### Defined in
|
||||
|
||||
[abs.ts:8](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/abs.ts#L8)
|
||||
[abs.ts:8](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/abs.ts#L8)
|
||||
|
||||
___
|
||||
|
||||
|
@ -67,7 +107,37 @@ The bit length
|
|||
|
||||
#### Defined in
|
||||
|
||||
[bitLength.ts:7](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/bitLength.ts#L7)
|
||||
[bitLength.ts:7](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/bitLength.ts#L7)
|
||||
|
||||
___
|
||||
|
||||
### crt
|
||||
|
||||
▸ **crt**(`remainders`, `modulos`, `modulo?`): `bigint`
|
||||
|
||||
Chinese remainder theorem states that if one knows the remainders of the Euclidean division of an integer n by several integers, then one can determine uniquely the remainder of the division of n by the product of these integers, under the condition that the divisors are pairwise coprime (no two divisors share a common factor other than 1). Provided that n_i are pairwise coprime, and a_i any integers, this function returns a solution for the following system of equations:
|
||||
x ≡ a_1 mod n_1
|
||||
x ≡ a_2 mod n_2
|
||||
⋮
|
||||
x ≡ a_k mod n_k
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `remainders` | `bigint`[] | the array of remainders a_i. For example [17n, 243n, 344n] |
|
||||
| `modulos` | `bigint`[] | the array of modulos n_i. For example [769n, 2017n, 47701n] |
|
||||
| `modulo?` | `bigint` | the product of all modulos. Provided here just to save some operations if it is already known |
|
||||
|
||||
#### Returns
|
||||
|
||||
`bigint`
|
||||
|
||||
x
|
||||
|
||||
#### Defined in
|
||||
|
||||
crt.ts:16
|
||||
|
||||
___
|
||||
|
||||
|
@ -97,7 +167,7 @@ A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|||
|
||||
#### Defined in
|
||||
|
||||
[egcd.ts:17](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/egcd.ts#L17)
|
||||
[egcd.ts:17](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/egcd.ts#L17)
|
||||
|
||||
___
|
||||
|
||||
|
@ -122,7 +192,7 @@ The greatest common divisor of a and b
|
|||
|
||||
#### Defined in
|
||||
|
||||
[gcd.ts:10](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/gcd.ts#L10)
|
||||
[gcd.ts:11](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/gcd.ts#L11)
|
||||
|
||||
___
|
||||
|
||||
|
@ -147,7 +217,7 @@ The least common multiple of a and b
|
|||
|
||||
#### Defined in
|
||||
|
||||
[lcm.ts:10](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/lcm.ts#L10)
|
||||
[lcm.ts:11](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/lcm.ts#L11)
|
||||
|
||||
___
|
||||
|
||||
|
@ -172,7 +242,7 @@ Maximum of numbers a and b
|
|||
|
||||
#### Defined in
|
||||
|
||||
[max.ts:9](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/max.ts#L9)
|
||||
[max.ts:9](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/max.ts#L9)
|
||||
|
||||
___
|
||||
|
||||
|
@ -197,7 +267,32 @@ Minimum of numbers a and b
|
|||
|
||||
#### Defined in
|
||||
|
||||
[min.ts:9](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/min.ts#L9)
|
||||
[min.ts:9](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/min.ts#L9)
|
||||
|
||||
___
|
||||
|
||||
### modAdd
|
||||
|
||||
▸ **modAdd**(`addends`, `n`): `bigint`
|
||||
|
||||
Modular addition of (a_1 + ... + a_r) mod n
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `addends` | (`number` \| `bigint`)[] | an array of the numbers a_i to add. For example [3, 12353251235n, 1243, -12341232545990n] |
|
||||
| `n` | `number` \| `bigint` | the modulo |
|
||||
|
||||
#### Returns
|
||||
|
||||
`bigint`
|
||||
|
||||
The smallest positive integer that is congruent with (a_1 + ... + a_r) mod n
|
||||
|
||||
#### Defined in
|
||||
|
||||
modAdd.ts:9
|
||||
|
||||
___
|
||||
|
||||
|
@ -226,15 +321,41 @@ The inverse modulo n
|
|||
|
||||
#### Defined in
|
||||
|
||||
[modInv.ts:13](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/modInv.ts#L13)
|
||||
[modInv.ts:14](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/modInv.ts#L14)
|
||||
|
||||
___
|
||||
|
||||
### modMultiply
|
||||
|
||||
▸ **modMultiply**(`factors`, `n`): `bigint`
|
||||
|
||||
Modular addition of (a_1 * ... * a_r) mod n
|
||||
*
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `factors` | (`number` \| `bigint`)[] | an array of the numbers a_i to multiply. For example [3, 12353251235n, 1243, -12341232545990n] * |
|
||||
| `n` | `number` \| `bigint` | the modulo * |
|
||||
|
||||
#### Returns
|
||||
|
||||
`bigint`
|
||||
|
||||
The smallest positive integer that is congruent with (a_1 * ... * a_r) mod n
|
||||
|
||||
#### Defined in
|
||||
|
||||
modMultiply.ts:9
|
||||
|
||||
___
|
||||
|
||||
### modPow
|
||||
|
||||
▸ **modPow**(`b`, `e`, `n`): `bigint`
|
||||
▸ **modPow**(`b`, `e`, `n`, `primeFactorization?`): `bigint`
|
||||
|
||||
Modular exponentiation b**e mod n. Currently using the right-to-left binary method
|
||||
Modular exponentiation b**e mod n. Currently using the right-to-left binary method if the prime factorization is not provided, or the chinese remainder theorem otherwise.
|
||||
|
||||
**`Throws`**
|
||||
|
||||
|
@ -247,6 +368,7 @@ RangeError if n <= 0
|
|||
| `b` | `number` \| `bigint` | base |
|
||||
| `e` | `number` \| `bigint` | exponent |
|
||||
| `n` | `number` \| `bigint` | modulo |
|
||||
| `primeFactorization?` | [`PrimeFactor`](API.md#primefactor)[] | an array of the prime factors, for example [5n, 5n, 13n, 27n], or prime powers as [p, k], for instance [[5, 2], [13, 1], [27, 1]]. If the prime factorization is provided the chinese remainder theorem is used to greatly speed up the exponentiation. |
|
||||
|
||||
#### Returns
|
||||
|
||||
|
@ -256,7 +378,31 @@ b**e mod n
|
|||
|
||||
#### Defined in
|
||||
|
||||
[modPow.ts:15](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/modPow.ts#L15)
|
||||
[modPow.ts:22](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/modPow.ts#L22)
|
||||
|
||||
___
|
||||
|
||||
### phi
|
||||
|
||||
▸ **phi**(`primeFactorization`): `bigint`
|
||||
|
||||
A function that computes the Euler's totien function of a number n, whose prime power factorization is known
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------ | :------ | :------ |
|
||||
| `primeFactorization` | [`PrimeFactorization`](API.md#primefactorization) | an array of arrays containing the prime power factorization, i.e. for n = (p1**k1)*(p2**k2)*...*(pr**kr), one should provide [[p1, k1], [p2, k2], ... , [pr, kr]] |
|
||||
|
||||
#### Returns
|
||||
|
||||
`bigint`
|
||||
|
||||
phi((p1**k1)*(p2**k2)*...*(pr**kr))
|
||||
|
||||
#### Defined in
|
||||
|
||||
phi.ts:9
|
||||
|
||||
___
|
||||
|
||||
|
@ -289,4 +435,4 @@ A bigint with the smallest positive representation of a modulo n
|
|||
|
||||
#### Defined in
|
||||
|
||||
[toZn.ts:14](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/toZn.ts#L14)
|
||||
[toZn.ts:14](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/toZn.ts#L14)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#### Defined in
|
||||
|
||||
[egcd.ts:2](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/egcd.ts#L2)
|
||||
[egcd.ts:2](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/egcd.ts#L2)
|
||||
|
||||
___
|
||||
|
||||
|
@ -26,7 +26,7 @@ ___
|
|||
|
||||
#### Defined in
|
||||
|
||||
[egcd.ts:3](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/egcd.ts#L3)
|
||||
[egcd.ts:3](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/egcd.ts#L3)
|
||||
|
||||
___
|
||||
|
||||
|
@ -36,4 +36,4 @@ ___
|
|||
|
||||
#### Defined in
|
||||
|
||||
[egcd.ts:4](https://github.com/juanelas/bigint-mod-arith/blob/84ebe88/src/ts/egcd.ts#L4)
|
||||
[egcd.ts:4](https://github.com/juanelas/bigint-mod-arith/blob/80793b3/src/ts/egcd.ts#L4)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
|
@ -50,10 +50,26 @@
|
|||
}
|
||||
},
|
||||
"./esm-browser-bundle": "./dist/bundle.esm.min.js",
|
||||
"./dist/bundle.esm.min.js": "./dist/bundle.esm.min.js",
|
||||
"./esm-browser-bundle-nomin": "./dist/bundle.esm.js",
|
||||
"./dist/bundle.esm.js": "./dist/bundle.esm.js",
|
||||
"./iife-browser-bundle": "./dist/bundle.iife.js",
|
||||
"./dist/bundle.iife.js": "./dist/bundle.iife.js",
|
||||
"./umd-browser-bundle": "./dist/bundle.umd.js",
|
||||
"./types": "./dist/index.d.ts"
|
||||
"./dist/bundle.umd.js": "./dist/bundle.umd.js",
|
||||
"./dist/index.node": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.node.cjs"
|
||||
},
|
||||
"./dist/index.node.esm": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.node.esm.js"
|
||||
},
|
||||
"./dist/index.browser.esm": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.browser.esm.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"imports": {
|
||||
"#pkg": {
|
||||
|
@ -66,7 +82,7 @@
|
|||
"default": "./dist/index.node.esm.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.browser.esm.js"
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +151,7 @@
|
|||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^24.0.1",
|
||||
"@rollup/plugin-commonjs": "^25.0.2",
|
||||
"@rollup/plugin-inject": "^5.0.3",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-multi-entry": "^6.0.0",
|
||||
|
@ -145,7 +161,7 @@
|
|||
"@rollup/plugin-typescript": "^11.1.0",
|
||||
"@types/chai": "^4.2.22",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"c8": "^7.12.0",
|
||||
"c8": "^8.0.0",
|
||||
"chai": "^4.3.3",
|
||||
"dotenv": "^16.0.3",
|
||||
"glob": "^10.0.0",
|
||||
|
@ -154,7 +170,7 @@
|
|||
"mocha": "^10.0.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"pirates": "^4.0.1",
|
||||
"puppeteer": "^19.1.2",
|
||||
"puppeteer": "^20.7.3",
|
||||
"rimraf": "^5.0.0",
|
||||
"rollup": "^3.20.2",
|
||||
"rollup-plugin-dts": "^5.3.0",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { abs } from './abs.js'
|
||||
|
||||
/**
|
||||
* Greatest common divisor of two integers based on the iterative binary algorithm.
|
||||
*
|
||||
|
|
|
@ -6,11 +6,15 @@
|
|||
|
||||
export { abs } from './abs.js'
|
||||
export { bitLength } from './bitLength.js'
|
||||
export { crt } from './crt.js'
|
||||
export { Egcd, eGcd } from './egcd.js'
|
||||
export { gcd } from './gcd.js'
|
||||
export { lcm } from './lcm.js'
|
||||
export { max } from './max.js'
|
||||
export { min } from './min.js'
|
||||
export { modAdd } from './modAdd.js'
|
||||
export { modInv } from './modInv.js'
|
||||
export { modPow } from './modPow.js'
|
||||
export { modMultiply } from './modMultiply.js'
|
||||
export { PrimeFactor, PrimePower, modPow } from './modPow.js'
|
||||
export { PrimeFactorization, phi } from './phi.js'
|
||||
export { toZn } from './toZn.js'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { abs } from './abs.js'
|
||||
import { gcd } from './gcd.js'
|
||||
|
||||
/**
|
||||
* The least common multiple computed as abs(a*b)/gcd(a,b)
|
||||
* @param a
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { eGcd } from './egcd.js'
|
||||
import { toZn } from './toZn.js'
|
||||
|
||||
/**
|
||||
* Modular inverse.
|
||||
*
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
import { abs } from './abs.js'
|
||||
import { crt } from './crt.js'
|
||||
import { modInv } from './modInv.js'
|
||||
import { PrimeFactorization, phi } from './phi.js'
|
||||
import { toZn } from './toZn.js'
|
||||
|
||||
export type PrimePower = [number | bigint, number | bigint] // [p, k] is for p**k
|
||||
export type PrimeFactor = number | bigint | PrimePower
|
||||
|
||||
/**
|
||||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method
|
||||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method if the prime factorization is not provided, or the chinese remainder theorem otherwise.
|
||||
*
|
||||
* @param b base
|
||||
* @param e exponent
|
||||
* @param n modulo
|
||||
* @param primeFactorization an array of the prime factors, for example [5n, 5n, 13n, 27n], or prime powers as [p, k], for instance [[5, 2], [13, 1], [27, 1]]. If the prime factorization is provided the chinese remainder theorem is used to greatly speed up the exponentiation.
|
||||
*
|
||||
* @throws {@link RangeError} if n <= 0
|
||||
*
|
||||
* @returns b**e mod n
|
||||
*/
|
||||
export function modPow (b: number | bigint, e: number | bigint, n: number | bigint): bigint {
|
||||
export function modPow (b: number | bigint, e: number | bigint, n: number | bigint, primeFactorization?: PrimeFactor[]): bigint {
|
||||
if (typeof b === 'number') b = BigInt(b)
|
||||
if (typeof e === 'number') e = BigInt(e)
|
||||
if (typeof n === 'number') n = BigInt(n)
|
||||
|
@ -26,7 +33,11 @@ export function modPow (b: number | bigint, e: number | bigint, n: number | bigi
|
|||
b = toZn(b, n)
|
||||
|
||||
if (e < 0n) {
|
||||
return modInv(modPow(b, abs(e), n), n)
|
||||
return modInv(modPow(b, abs(e), n, primeFactorization), n)
|
||||
}
|
||||
|
||||
if (primeFactorization !== undefined) {
|
||||
return modPowWithFactorization(b, e, n, primePowerArguments(primeFactorization))
|
||||
}
|
||||
|
||||
let r = 1n
|
||||
|
@ -39,3 +50,39 @@ export function modPow (b: number | bigint, e: number | bigint, n: number | bigi
|
|||
}
|
||||
return r
|
||||
}
|
||||
|
||||
function primePowerArguments (primeFactors: PrimeFactor[]): PrimeFactorization {
|
||||
interface PrimePowers {
|
||||
[p: string]: {
|
||||
p: bigint
|
||||
k: bigint
|
||||
}
|
||||
}
|
||||
const primePowers: PrimePowers = {}
|
||||
primeFactors.forEach((primeFactor: PrimeFactor) => {
|
||||
if (typeof primeFactor === 'bigint' || typeof primeFactor === 'number') {
|
||||
const key = String(primeFactor)
|
||||
if (primePowers[key] === undefined) {
|
||||
primePowers[key] = { p: BigInt(primeFactor), k: 1n }
|
||||
} else {
|
||||
primePowers[key].k += 1n
|
||||
}
|
||||
} else {
|
||||
const key = String(primeFactor[0])
|
||||
if (primePowers[key] === undefined) {
|
||||
primePowers[key] = { p: BigInt(primeFactor[0]), k: BigInt(primeFactor[1]) }
|
||||
} else {
|
||||
primePowers[key].k += BigInt(primeFactor[1])
|
||||
}
|
||||
}
|
||||
})
|
||||
return Object.values(primePowers).map(val => [val.p, val.k])
|
||||
}
|
||||
|
||||
function modPowWithFactorization (b: bigint, e: bigint, n: bigint, primeFactorization: PrimeFactorization): bigint {
|
||||
const mods = primeFactorization.map(v => v[0] ** v[1])
|
||||
const phis = primeFactorization.map(v => phi([v]))
|
||||
const remainders = phis.map((phi, i) => modPow(b, e % phi, mods[i]))
|
||||
|
||||
return crt(remainders, mods, n)
|
||||
}
|
||||
|
|
|
@ -24,13 +24,58 @@ describe('modPow', function () {
|
|||
a: 2,
|
||||
b: BigInt(255),
|
||||
n: BigInt(64),
|
||||
modPow: BigInt(0)
|
||||
modPow: BigInt(0),
|
||||
factorization: [
|
||||
[2n, 6n] as [bigint, bigint]
|
||||
]
|
||||
},
|
||||
{
|
||||
a: BigInt(3),
|
||||
b: BigInt(3),
|
||||
n: BigInt(25),
|
||||
modPow: BigInt(2)
|
||||
},
|
||||
{
|
||||
a: 1245124521461246134613464612465425n,
|
||||
b: 9861532432154028374523497086414586n,
|
||||
n: 500153323344587826888856848415851710985056973082286918972465210560564286327935715658989361814629267526408365126549790626298674370641919299205366510873756645480988096218726721049169354944272728793562147809267541398194457197043260189n,
|
||||
modPow: 240451691789770161942445790505417018856065097712648273113407316782091824158551945401793333941917448724323499865320019414055693250255681376010258044942735855039307823617978628203426153507803442305305788129411652227222626528677503357n,
|
||||
factorization: [
|
||||
218230499735828681265329912048785421189n,
|
||||
303663914757588658442322995331731552767n,
|
||||
330074629227155283615948126790169269393n,
|
||||
318474781297924758545194431666113118619n,
|
||||
258866136593300047022978927175555617677n,
|
||||
277352503791024309522752317490262967817n
|
||||
]
|
||||
},
|
||||
{
|
||||
a: 14,
|
||||
b: 7,
|
||||
n: 75,
|
||||
modPow: (14n ** 7n) % 75n,
|
||||
factorization: [5, 5, 3]
|
||||
},
|
||||
{
|
||||
a: 14,
|
||||
b: 7,
|
||||
n: 75,
|
||||
modPow: (14n ** 7n) % 75n,
|
||||
factorization: [
|
||||
[5, 2],
|
||||
[3, 1]
|
||||
] as Array<[number, number]>
|
||||
},
|
||||
{
|
||||
a: 14,
|
||||
b: 7,
|
||||
n: 75,
|
||||
modPow: (14n ** 7n) % 75n,
|
||||
factorization: [
|
||||
[5, 1],
|
||||
[5, 1],
|
||||
[3, 1]
|
||||
] as Array<[number, number]>
|
||||
}
|
||||
]
|
||||
const invalidInputs = [
|
||||
|
@ -49,6 +94,14 @@ describe('modPow', function () {
|
|||
chai.expect(String(ret)).to.equal(String(input.modPow))
|
||||
})
|
||||
})
|
||||
if (input.factorization !== undefined) {
|
||||
describe(`modPow(${input.a}, ${input.b}, ${input.n}, ${input.factorization.toString()})`, function () {
|
||||
it(`should return ${input.modPow}`, function () {
|
||||
const ret = bma.modPow(input.a, input.b, input.n, input.factorization)
|
||||
chai.expect(String(ret)).to.equal(String(input.modPow))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
for (const input of invalidInputs) {
|
||||
describe(`modPow(${input.a}, ${input.b}, ${input.n})`, function () {
|
||||
|
@ -63,15 +116,37 @@ describe('modPow', function () {
|
|||
})
|
||||
}
|
||||
describe('Time profiling', function () {
|
||||
let iterations = 500
|
||||
it(`just testing ${iterations} iterations of a big modular exponentiation (1024 bits)`, function () {
|
||||
const p = BigInt('103920301461718841589267304263845359224454055603847417021399996422142529929535423886894599506329362009085557636432288745748144369296043048325513558512136442971686130986388589421125262751724362880217790112013162815676017250234401214198365302142787009943498370856167174244675719638815809347261773472114842038647')
|
||||
const b = BigInt('313632271690673451924314047671460131678794095260951233878123501752357966284491455239133687519908410656818506813151659324961829045286402303082891913186909806785080978448037486178337722667190743610785429936585699831407575170854873682955317589189564880931807976657385223632835801016017549762825562427694700595')
|
||||
const e = BigInt('452149997592306202232720864363485824701879487303880767747217308770351197801836846325633986474037061753983278534192061455638289551714281047915315943771002615269860312318606105460307037327329178890486613832051027105330475852552183444938408408863970975090778239473049899109989825645608770309107015209564444316')
|
||||
let iterations = 200
|
||||
it(`just testing ${iterations} iterations of a big modular exponentiation (2556 bits) without knowing the factorization`, function () {
|
||||
const b = 14456431150320172221616509514915526986361238106327826551303073486525612767865296230128540157601034246266893020552680362383297675100669325175361571346279322237329539671666972989978592763343703141198972640627941866075477300010699834312750158094259287059018038648351844386887485449450696346016139524199689991349708808322654998848805208669420846568444495238595132694793197702398883664520354286998606227508937724093725751362231924270085297872354786607945787781132474291940577910417557559293025781300297297108502666688221522472289490235815670978276613741134646350434101590756987811531081642032408524942596500338402454466381n
|
||||
const e = 6476828424489334540282736436237684965801863681796103123350476262449294411071194504043425154023126089205310946452545492503146985930350204469300515359582715304152166280054365341048395809786334314857324636363499307693460463510288529968621389225833525926438586030988343742064052508822378379640511991190252363284703683198952353035019752852304188032580325320976126425473699273404534699914473174622613565918567472049036606462965033376292343629368800907251671928637057211397168781968913665986137146419257679003630816671501426427417948524164164352320112674416922816719009895345189205426946805834621054179616261802871233808542n
|
||||
const p = 14042712215688595888153548037889265603500445396639048834534593945467996508131090693365705725532399000992101105698944349047255173597667719370418259169482368508397450171314103850946590710597528264317201250415269575297721977669910571659769606054734401815045082525419212665804298903457270476082779587884970903510490346851467622773314340966549056833592925777140709340896303359906331395892064520612544700229681757412030739888382792194999476266900467607277786534152843408108882693507381781909441777014175765880808549111456404523289456415574592100070259890096499076724913855490255757168221008761519287520710678016476002003203122666993484494111951001896014648841958164118312595430383512299989338389906619375114947097244226374433271798549164684597345168487916487128962249635970759n
|
||||
while (iterations > 0) {
|
||||
bma.modPow(b, e, p)
|
||||
iterations--
|
||||
}
|
||||
})
|
||||
let iterations2 = 200
|
||||
it(`just testing ${iterations2} iterations of a big modular exponentiation (2556 bits) knowing the factorization`, function () {
|
||||
const b = 14456431150320172221616509514915526986361238106327826551303073486525612767865296230128540157601034246266893020552680362383297675100669325175361571346279322237329539671666972989978592763343703141198972640627941866075477300010699834312750158094259287059018038648351844386887485449450696346016139524199689991349708808322654998848805208669420846568444495238595132694793197702398883664520354286998606227508937724093725751362231924270085297872354786607945787781132474291940577910417557559293025781300297297108502666688221522472289490235815670978276613741134646350434101590756987811531081642032408524942596500338402454466381n
|
||||
const e = 6476828424489334540282736436237684965801863681796103123350476262449294411071194504043425154023126089205310946452545492503146985930350204469300515359582715304152166280054365341048395809786334314857324636363499307693460463510288529968621389225833525926438586030988343742064052508822378379640511991190252363284703683198952353035019752852304188032580325320976126425473699273404534699914473174622613565918567472049036606462965033376292343629368800907251671928637057211397168781968913665986137146419257679003630816671501426427417948524164164352320112674416922816719009895345189205426946805834621054179616261802871233808542n
|
||||
const p = 14042712215688595888153548037889265603500445396639048834534593945467996508131090693365705725532399000992101105698944349047255173597667719370418259169482368508397450171314103850946590710597528264317201250415269575297721977669910571659769606054734401815045082525419212665804298903457270476082779587884970903510490346851467622773314340966549056833592925777140709340896303359906331395892064520612544700229681757412030739888382792194999476266900467607277786534152843408108882693507381781909441777014175765880808549111456404523289456415574592100070259890096499076724913855490255757168221008761519287520710678016476002003203122666993484494111951001896014648841958164118312595430383512299989338389906619375114947097244226374433271798549164684597345168487916487128962249635970759n
|
||||
const factorization = [
|
||||
64735041287835073339645110378796758902638279101014381826528695387496122442691n,
|
||||
100608456040189246257906094489725850536673092825529567729728751391736301991369n,
|
||||
58992718408385655584411200892712190864864350334099743757220725378063820240657n,
|
||||
96562131825975924912838022675233698320760586729314385931723127363428962983247n,
|
||||
68620104844493133229164822823175832794894654493599547904820655831878232061531n,
|
||||
71474468886948151751742173259692288576445414562898468020644046548578552084431n,
|
||||
96793884673833556249816099345608529931050134280462961194018209385115828684189n,
|
||||
94085307601549784597508419912586171618182711224796241928810495401174923988119n,
|
||||
91841918562944515248478087657554520191420619060733607414018266296555587309041n,
|
||||
92269642318171922312931975258187595106742943586895754768486213552371747180589n
|
||||
]
|
||||
while (iterations2 > 0) {
|
||||
bma.modPow(b, e, p, factorization)
|
||||
iterations2--
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue