modpow with crt; crt; modAdd; modMultiply; phi

This commit is contained in:
Juanelas 2023-06-28 19:38:17 +02:00
parent 7ae82f2c21
commit e015a51c80
10 changed files with 173 additions and 15 deletions

4
dist/bundle.esm.js vendored
View File

@ -1,4 +1,4 @@
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 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} 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}
function fromBuffer(buf) { function fromBuffer(buf) {
let ret = 0n; let ret = 0n;
@ -530,4 +530,4 @@ function primeSync(bitLength, iterations = 16) {
return rnd; return rnd;
} }
export { n as abs, t as bitLength, r as eGcd, u as gcd, isProbablyPrime, f as lcm, g as max, c as min, o as modInv, s as modPow, prime, primeSync, randBetween, randBits, randBitsSync, randBytes, randBytesSync, e as toZn }; export { n as abs, t as bitLength, i as crt, r as eGcd, u as gcd, isProbablyPrime, f as lcm, g as max, c as min, m as modAdd, o as modInv, p as modMultiply, s as modPow, a as phi, prime, primeSync, randBetween, randBits, randBitsSync, randBytes, randBytesSync, e as toZn };

File diff suppressed because one or more lines are too long

2
dist/bundle.iife.js vendored

File diff suppressed because one or more lines are too long

2
dist/bundle.umd.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

41
dist/index.d.ts vendored
View File

@ -16,6 +16,20 @@ declare function abs(a: number | bigint): number | bigint;
*/ */
declare function bitLength(a: number | bigint): number; declare function bitLength(a: number | bigint): number;
/**
* 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
*
* @param remainders the array of remainders a_i. For example [17n, 243n, 344n]
* @param modulos the array of modulos n_i. For example [769n, 2017n, 47701n]
* @param modulo the product of all modulos. Provided here just to save some operations if it is already known
* @returns x
*/
declare function crt(remainders: bigint[], modulos: bigint[], modulo?: bigint): bigint;
interface Egcd { interface Egcd {
g: bigint; g: bigint;
x: bigint; x: bigint;
@ -73,6 +87,14 @@ declare function max(a: number | bigint, b: number | bigint): number | bigint;
*/ */
declare function min(a: number | bigint, b: number | bigint): number | bigint; declare function min(a: number | bigint, b: number | bigint): number | bigint;
/**
* Modular addition of (a_1 + ... + a_r) mod n
* @param addends an array of the numbers a_i to add. For example [3, 12353251235n, 1243, -12341232545990n]
* @param n the modulo
* @returns The smallest positive integer that is congruent with (a_1 + ... + a_r) mod n
*/
declare function modAdd(addends: Array<number | bigint>, n: number | bigint): bigint;
/** /**
* Modular inverse. * Modular inverse.
* *
@ -85,6 +107,14 @@ declare function min(a: number | bigint, b: number | bigint): number | bigint;
*/ */
declare function modInv(a: number | bigint, n: number | bigint): bigint; declare function modInv(a: number | bigint, n: number | bigint): bigint;
/**
* Modular addition of (a_1 * ... * a_r) mod n
* @param factors an array of the numbers a_i to multiply. For example [3, 12353251235n, 1243, -12341232545990n]
* @param n the modulo
* @returns The smallest positive integer that is congruent with (a_1 * ... * a_r) mod n
*/
declare function modMultiply(factors: Array<number | bigint>, n: number | bigint): bigint;
type PrimePower = [number | bigint, number | bigint]; type PrimePower = [number | bigint, number | bigint];
type PrimeFactor = number | bigint | PrimePower; type PrimeFactor = number | bigint | PrimePower;
/** /**
@ -101,6 +131,15 @@ type PrimeFactor = number | bigint | PrimePower;
*/ */
declare function modPow(b: number | bigint, e: number | bigint, n: number | bigint, primeFactorization?: PrimeFactor[]): bigint; declare function modPow(b: number | bigint, e: number | bigint, n: number | bigint, primeFactorization?: PrimeFactor[]): bigint;
type PrimeFactorization = Array<[bigint, bigint]>;
/**
* A function that computes the Euler's totien function of a number n, whose prime power factorization is known
*
* @param primeFactorization an array of arrays containing the prime power factorization of a number n. For example, for n = (p1**k1)*(p2**k2)*...*(pr**kr), one should provide [[p1, k1], [p2, k2], ... , [pr, kr]]
* @returns phi((p1**k1)*(p2**k2)*...*(pr**kr))
*/
declare function phi(primeFactorization: PrimeFactorization): bigint;
/** /**
* Finds the smallest positive element that is congruent to a in modulo n * Finds the smallest positive element that is congruent to a in modulo n
* *
@ -215,4 +254,4 @@ declare function randBytes(byteLength: number, forceLength?: boolean): Promise<U
*/ */
declare function randBytesSync(byteLength: number, forceLength?: boolean): Uint8Array | Buffer; declare function randBytesSync(byteLength: number, forceLength?: boolean): Uint8Array | Buffer;
export { abs, bitLength, eGcd, gcd, isProbablyPrime, lcm, max, min, modInv, modPow, prime, primeSync, randBetween, randBits, randBitsSync, randBytes, randBytesSync, toZn }; export { Egcd, PrimeFactor, PrimeFactorization, PrimePower, abs, bitLength, crt, eGcd, gcd, isProbablyPrime, lcm, max, min, modAdd, modInv, modMultiply, modPow, phi, prime, primeSync, randBetween, randBits, randBitsSync, randBytes, randBytesSync, toZn };

3
dist/index.node.cjs vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,18 +2,32 @@
## Table of contents ## Table of contents
### Interfaces
- [Egcd](interfaces/Egcd.md)
### Type Aliases
- [PrimeFactor](API.md#primefactor)
- [PrimeFactorization](API.md#primefactorization)
- [PrimePower](API.md#primepower)
### Functions ### Functions
- [abs](API.md#abs) - [abs](API.md#abs)
- [bitLength](API.md#bitlength) - [bitLength](API.md#bitlength)
- [crt](API.md#crt)
- [eGcd](API.md#egcd) - [eGcd](API.md#egcd)
- [gcd](API.md#gcd) - [gcd](API.md#gcd)
- [isProbablyPrime](API.md#isprobablyprime) - [isProbablyPrime](API.md#isprobablyprime)
- [lcm](API.md#lcm) - [lcm](API.md#lcm)
- [max](API.md#max) - [max](API.md#max)
- [min](API.md#min) - [min](API.md#min)
- [modAdd](API.md#modadd)
- [modInv](API.md#modinv) - [modInv](API.md#modinv)
- [modMultiply](API.md#modmultiply)
- [modPow](API.md#modpow) - [modPow](API.md#modpow)
- [phi](API.md#phi)
- [prime](API.md#prime) - [prime](API.md#prime)
- [primeSync](API.md#primesync) - [primeSync](API.md#primesync)
- [randBetween](API.md#randbetween) - [randBetween](API.md#randbetween)
@ -23,6 +37,24 @@
- [randBytesSync](API.md#randbytessync) - [randBytesSync](API.md#randbytessync)
- [toZn](API.md#tozn) - [toZn](API.md#tozn)
## Type Aliases
### PrimeFactor
Ƭ **PrimeFactor**: `number` \| `bigint` \| [`PrimePower`](API.md#primepower)
___
### PrimeFactorization
Ƭ **PrimeFactorization**: [`bigint`, `bigint`][]
___
### PrimePower
Ƭ **PrimePower**: [`number` \| `bigint`, `number` \| `bigint`]
## Functions ## Functions
### abs ### abs
@ -65,9 +97,35 @@ The bit length
___ ___
### 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
___
### eGcd ### eGcd
**eGcd**(`a`, `b`): `Egcd` **eGcd**(`a`, `b`): [`Egcd`](interfaces/Egcd.md)
An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm. 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). Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -85,7 +143,7 @@ RangeError if a or b are <= 0
#### Returns #### Returns
`Egcd` [`Egcd`](interfaces/Egcd.md)
A triple (g, x, y), such that ax + by = g = gcd(a, b). A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -202,6 +260,27 @@ Minimum of numbers a and b
___ ___
### 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
___
### modInv ### modInv
**modInv**(`a`, `n`): `bigint` **modInv**(`a`, `n`): `bigint`
@ -227,6 +306,28 @@ The inverse modulo n
___ ___
### 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
___
### modPow ### modPow
**modPow**(`b`, `e`, `n`, `primeFactorization?`): `bigint` **modPow**(`b`, `e`, `n`, `primeFactorization?`): `bigint`
@ -244,7 +345,7 @@ RangeError if n <= 0
| `b` | `number` \| `bigint` | base | | `b` | `number` \| `bigint` | base |
| `e` | `number` \| `bigint` | exponent | | `e` | `number` \| `bigint` | exponent |
| `n` | `number` \| `bigint` | modulo | | `n` | `number` \| `bigint` | modulo |
| `primeFactorization?` | `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. | | `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 #### Returns
@ -254,6 +355,26 @@ b**e mod n
___ ___
### 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 of a number n. For example, 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))
___
### prime ### prime
**prime**(`bitLength`, `iterations?`): `Promise`<`bigint`\> **prime**(`bitLength`, `iterations?`): `Promise`<`bigint`\>

View File

@ -1,4 +1,4 @@
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn } from 'bigint-mod-arith' export * from 'bigint-mod-arith'
export { isProbablyPrime } from './isProbablyPrime.js' export { isProbablyPrime } from './isProbablyPrime.js'
export { prime, primeSync } from './prime.js' export { prime, primeSync } from './prime.js'