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) {
let ret = 0n;
@ -530,4 +530,4 @@ function primeSync(bitLength, iterations = 16) {
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;
/**
* 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 {
g: 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;
/**
* 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.
*
@ -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;
/**
* 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 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;
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
*
@ -215,4 +254,4 @@ declare function randBytes(byteLength: number, forceLength?: boolean): Promise<U
*/
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
### Interfaces
- [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)
- [isProbablyPrime](API.md#isprobablyprime)
- [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)
- [prime](API.md#prime)
- [primeSync](API.md#primesync)
- [randBetween](API.md#randbetween)
@ -23,6 +37,24 @@
- [randBytesSync](API.md#randbytessync)
- [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
### 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**(`a`, `b`): `Egcd`
**eGcd**(`a`, `b`): [`Egcd`](interfaces/Egcd.md)
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).
@ -85,7 +143,7 @@ RangeError if a or b are <= 0
#### Returns
`Egcd`
[`Egcd`](interfaces/Egcd.md)
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**(`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**(`b`, `e`, `n`, `primeFactorization?`): `bigint`
@ -244,7 +345,7 @@ RangeError if n <= 0
| `b` | `number` \| `bigint` | base |
| `e` | `number` \| `bigint` | exponent |
| `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
@ -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**(`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 { prime, primeSync } from './prime.js'