Better code structure. Better README. Added generation of IIFE file-a

This commit is contained in:
Juan Hernández Serrano 2019-04-25 17:24:29 +02:00
parent 35197cb809
commit 68b8eebe8a
10 changed files with 486 additions and 386 deletions

68
.gitignore vendored Normal file
View File

@ -0,0 +1,68 @@
# Project specific files
dist/bigint-mod-arith-?.?.?.*
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next
# Visual Studio Code
.vscode

View File

@ -1,62 +1,52 @@
# bigint-mod-arith # bigint-mod-arith
Some extra functions to work with modular arithmetics using native JS (stage 3) implementation of BigInt. It can be used Some extra functions to work with modular arithmetics using native JS (stage 3) implementation of BigInt. It can be used by any [Web Browser or webview supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) and with Node.js (>=10.4.0).
with Node.js (>=10.4.0) and [Web Browsers supporting
BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility).
If you are looking for a cryptographically secure random generator and for probale primes (generation and testing), you If you are looking for a cryptographically-secure random generator and for strong probable primes (generation and testing), you
may be interested in [bigint-secrets](https://github.com/juanelas/bigint-secrets) may be interested in [bigint-secrets](https://github.com/juanelas/bigint-secrets)
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in _The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html)._
cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html)**_
Many platforms provide native support for cryptography, such as
[webcrypto](https://w3c.github.io/webcrypto/Overview.html) or [node
crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
## Installation ## Installation
bigint-mod-arith is distributed as both an ES6 and a CJS module. bigint-mod-arith is distributed for [web browsers and/or webviews supporting
BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility)
The ES6 module is built for any [web browser supporting as an ES6 module or an IIFE file; and for Node.js (>=10.4.0), as a CJS module.
BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility).
The module only uses native javascript implementations and no polyfills had been applied.
The CJS module is built as a standard node module.
bigint-mod-arith can be imported to your project with `npm`: bigint-mod-arith can be imported to your project with `npm`:
```bash ```bash
npm install bigint-mod-arith npm install bigint-mod-arith
``` ```
NPM installation defaults to the ES6 module for browsers and the CJS one for Node.js.
For web browsers, you can also [download the bundle from For web browsers, you can also directly download the minimised version of the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js) from GitHub.
GitHub](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js).
## Usage examples ## Usage example
With node js: With node js:
```javascript ```javascript
const bigintModArith = require('bigint-mod-arith'); const bigintModArith = require('bigint-mod-arith');
// Stage 3 BigInts with value 666 can be declared as BigInt('666') /* Stage 3 BigInts with value 666 can be declared as BigInt('666')
// or the shorter no-linter-friendly new syntax 666n or the shorter new no-so-linter-friendly syntax 666n.
Notice that you can also pass a number, e.g. BigInt(666), but it is not
recommended since values over 2**53 - 1 won't be safe but no warning will
be raised.
*/
let a = BigInt('5'); let a = BigInt('5');
let b = BigInt('2'); let b = BigInt('2');
let n = BigInt('19'); let n = BigInt('19');
console.log(bigintModArith.modPow(a, b, n)); // prints 6 console.log(bigintCryptoUtils.modPow(a, b, n)); // prints 6
console.log(bigintModArith.modInv(BigInt('2'), BigInt('5'))); // prints 3 console.log(bigintCryptoUtils.modInv(BigInt('2'), BigInt('5'))); // prints 3
console.log(bigintModArith.modInv(BigInt('3'), BigInt('5'))); // prints 2 console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))); // prints 2
``` ```
From a browser, you can just load the module in a html page as: From a browser, you can just load the module in a html page as:
```html ```html
<script type="module"> <script type="module">
import * as bigintModArith from 'bigint-mod-arith-latest.browser.mod.min.js'; import * as bigintModArith from 'bigint-mod-arith-latest.browser.mod.min.js';
// Stage 3 BigInts with value 666 can be declared as BigInt('666')
// or the shorter no-linter-friendly new syntax 666n
let a = BigInt('5'); let a = BigInt('5');
let b = BigInt('2'); let b = BigInt('2');

124
README.md
View File

@ -1,47 +1,63 @@
# bigint-mod-arith # bigint-mod-arith
Some extra functions to work with modular arithmetics using native JS (stage 3) implementation of BigInt. It can be used with Node.js (>=10.4.0) and [Web Browsers supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility). Some extra functions to work with modular arithmetics using native JS (stage 3) implementation of BigInt. It can be used by any [Web Browser or webview supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) and with Node.js (>=10.4.0).
If you are looking for a cryptographically secure random generator and for probale primes (generation and testing), you may be interested in [bigint-secrets](https://github.com/juanelas/bigint-secrets) If you are looking for a cryptographically-secure random generator and for strong probable primes (generation and testing), you
may be interested in [bigint-secrets](https://github.com/juanelas/bigint-secrets)
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html)**_ _The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html)._
Many platforms provide native support for cryptography, such as [webcrypto](https://w3c.github.io/webcrypto/Overview.html) or [node crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
## Installation ## Installation
bigint-mod-arith is distributed as both an ES6 and a CJS module. bigint-mod-arith is distributed for [web browsers and/or webviews supporting
BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility)
The ES6 module is built for any [web browser supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility). The module only uses native javascript implementations and no polyfills had been applied. as an ES6 module or an IIFE file; and for Node.js (>=10.4.0), as a CJS module.
The CJS module is built as a standard node module.
bigint-mod-arith can be imported to your project with `npm`: bigint-mod-arith can be imported to your project with `npm`:
```bash ```bash
npm install bigint-mod-arith npm install bigint-mod-arith
``` ```
NPM installation defaults to the ES6 module for browsers and the CJS one for Node.js.
For web browsers, you can also [download the bundle from GitHub](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js) or just hotlink to it: For web browsers, you can also directly download the minimised version of the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js) from GitHub.
```html
<script type="module" src="https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js"></script>
```
## Usage examples ## Usage example
With node js:
```javascript ```javascript
const bigintModArith = require('bigint-mod-arith'); const bigintModArith = require('bigint-mod-arith');
// Stage 3 BigInts with value 666 can be declared as BigInt('666') /* Stage 3 BigInts with value 666 can be declared as BigInt('666')
// or the shorter no-linter-friendly new syntax 666n or the shorter new no-so-linter-friendly syntax 666n.
Notice that you can also pass a number, e.g. BigInt(666), but it is not
recommended since values over 2**53 - 1 won't be safe but no warning will
be raised.
*/
let a = BigInt('5'); let a = BigInt('5');
let b = BigInt('2'); let b = BigInt('2');
let n = BigInt('19'); let n = BigInt('19');
console.log(bigintModArith.modPow(a, b, n)); // prints 6 console.log(bigintCryptoUtils.modPow(a, b, n)); // prints 6
console.log(bigintModArith.modInv(BigInt('2'), BigInt('5'))); // prints 3 console.log(bigintCryptoUtils.modInv(BigInt('2'), BigInt('5'))); // prints 3
console.log(bigintModArith.modInv(BigInt('3'), BigInt('5'))); // prints 2 console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))); // prints 2
```
From a browser, you can just load the module in a html page as:
```html
<script type="module">
import * as bigintModArith from 'bigint-mod-arith-latest.browser.mod.min.js';
let a = BigInt('5');
let b = BigInt('2');
let n = BigInt('19');
console.log(bigintModArith.modPow(a, b, n)); // prints 6
console.log(bigintModArith.modInv(BigInt('2'), BigInt('5'))); // prints 3
console.log(bigintModArith.modInv(BigInt('3'), BigInt('5'))); // prints 2
</script>
``` ```
# bigint-mod-arith JS Doc # bigint-mod-arith JS Doc
@ -52,25 +68,25 @@ console.log(bigintModArith.modInv(BigInt('3'), BigInt('5'))); // prints 2
<dt><a href="#abs">abs(a)</a><code>bigint</code></dt> <dt><a href="#abs">abs(a)</a><code>bigint</code></dt>
<dd><p>Absolute value. abs(a)==a if a&gt;=0. abs(a)==-a if a&lt;0</p> <dd><p>Absolute value. abs(a)==a if a&gt;=0. abs(a)==-a if a&lt;0</p>
</dd> </dd>
<dt><a href="#eGcd">eGcd(a, b)</a><code><a href="#egcdReturn">egcdReturn</a></code></dt>
<dd><p>An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).</p>
</dd>
<dt><a href="#gcd">gcd(a, b)</a><code>bigint</code></dt> <dt><a href="#gcd">gcd(a, b)</a><code>bigint</code></dt>
<dd><p>Greatest-common divisor of two integers based on the iterative binary algorithm.</p> <dd><p>Greatest-common divisor of two integers based on the iterative binary algorithm.</p>
</dd> </dd>
<dt><a href="#lcm">lcm(a, b)</a><code>bigint</code></dt> <dt><a href="#lcm">lcm(a, b)</a><code>bigint</code></dt>
<dd><p>The least common multiple computed as abs(a*b)/gcd(a,b)</p> <dd><p>The least common multiple computed as abs(a*b)/gcd(a,b)</p>
</dd> </dd>
<dt><a href="#toZn">toZn(a, n)</a><code>bigint</code></dt>
<dd><p>Finds the smallest positive element that is congruent to a in modulo n</p>
</dd>
<dt><a href="#eGcd">eGcd(a, b)</a><code><a href="#egcdReturn">egcdReturn</a></code></dt>
<dd><p>An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).</p>
</dd>
<dt><a href="#modInv">modInv(a, n)</a><code>bigint</code></dt> <dt><a href="#modInv">modInv(a, n)</a><code>bigint</code></dt>
<dd><p>Modular inverse.</p> <dd><p>Modular inverse.</p>
</dd> </dd>
<dt><a href="#modPow">modPow(a, b, n)</a><code>bigint</code></dt> <dt><a href="#modPow">modPow(a, b, n)</a><code>bigint</code></dt>
<dd><p>Modular exponentiation a**b mod n</p> <dd><p>Modular exponentiation a**b mod n</p>
</dd> </dd>
<dt><a href="#toZn">toZn(a, n)</a><code>bigint</code></dt>
<dd><p>Finds the smallest positive element that is congruent to a in modulo n</p>
</dd>
</dl> </dl>
## Typedefs ## Typedefs
@ -93,6 +109,19 @@ Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
| --- | --- | | --- | --- |
| a | <code>number</code> \| <code>bigint</code> | | a | <code>number</code> \| <code>bigint</code> |
<a name="eGcd"></a>
## eGcd(a, b) ⇒ [<code>egcdReturn</code>](#egcdReturn)
An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
**Kind**: global function
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="gcd"></a> <a name="gcd"></a>
## gcd(a, b) ⇒ <code>bigint</code> ## gcd(a, b) ⇒ <code>bigint</code>
@ -119,32 +148,6 @@ The least common multiple computed as abs(a*b)/gcd(a,b)
| a | <code>number</code> \| <code>bigint</code> | | a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> | | b | <code>number</code> \| <code>bigint</code> |
<a name="toZn"></a>
## toZn(a, n) ⇒ <code>bigint</code>
Finds the smallest positive element that is congruent to a in modulo n
**Kind**: global function
**Returns**: <code>bigint</code> - The smallest positive representation of a in modulo n
| Param | Type | Description |
| --- | --- | --- |
| a | <code>number</code> \| <code>bigint</code> | An integer |
| n | <code>number</code> \| <code>bigint</code> | The modulo |
<a name="eGcd"></a>
## eGcd(a, b) ⇒ [<code>egcdReturn</code>](#egcdReturn)
An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
**Kind**: global function
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="modInv"></a> <a name="modInv"></a>
## modInv(a, n) ⇒ <code>bigint</code> ## modInv(a, n) ⇒ <code>bigint</code>
@ -172,6 +175,19 @@ Modular exponentiation a**b mod n
| b | <code>number</code> \| <code>bigint</code> | exponent | | b | <code>number</code> \| <code>bigint</code> | exponent |
| n | <code>number</code> \| <code>bigint</code> | modulo | | n | <code>number</code> \| <code>bigint</code> | modulo |
<a name="toZn"></a>
## toZn(a, n) ⇒ <code>bigint</code>
Finds the smallest positive element that is congruent to a in modulo n
**Kind**: global function
**Returns**: <code>bigint</code> - The smallest positive representation of a in modulo n
| Param | Type | Description |
| --- | --- | --- |
| a | <code>number</code> \| <code>bigint</code> | An integer |
| n | <code>number</code> \| <code>bigint</code> | The modulo |
<a name="egcdReturn"></a> <a name="egcdReturn"></a>
## egcdReturn : <code>Object</code> ## egcdReturn : <code>Object</code>

View File

@ -1,48 +1,73 @@
'use strict';
const rollup = require('rollup'); const rollup = require('rollup');
const commonjs = require('rollup-plugin-commonjs');
const minify = require('rollup-plugin-babel-minify'); const minify = require('rollup-plugin-babel-minify');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const pkgJson = require('../package.json'); const pkgJson = require('../package.json');
const rootDir = path.join(__dirname, '..');
const srcDir = path.join(rootDir, 'src');
const dstDir = path.join(rootDir, 'dist');
const buildOptions = [ const buildOptions = [
{ // Browser { // Browser
input: { input: {
input: path.join(__dirname, '..', 'src', 'main.js'), input: path.join(srcDir, 'main.js')
plugins: [
commonjs()
],
}, },
output: { output: {
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.browser.mod.js`), file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.js`),
format: 'esm' format: 'iife',
name: camelise(pkgJson.name)
} }
}, },
{ // Browser minified { // Browser minified
input: { input: {
input: path.join(__dirname, '..', 'src', 'main.js'), input: path.join(srcDir, 'main.js'),
plugins: [ plugins: [
commonjs(),
minify({ minify({
'comments': false 'comments': false
}) })
], ],
}, },
output: { output: {
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.browser.mod.min.js`), file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.min.js`),
format: 'iife',
name: camelise(pkgJson.name)
}
},
{ // Browser esm
input: {
input: path.join(srcDir, 'main.js')
},
output: {
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.mod.js`),
format: 'esm'
}
},
{ // Browser esm minified
input: {
input: path.join(srcDir, 'main.js'),
plugins: [
minify({
'comments': false
})
],
},
output: {
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.mod.min.js`),
format: 'esm' format: 'esm'
} }
}, },
{ // Node { // Node
input: { input: {
input: path.join(__dirname, '..', 'src', 'main.js'), input: path.join(srcDir, 'main.js'),
}, },
output: { output: {
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.node.js`), file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.node.js`),
format: 'cjs' format: 'cjs'
} }
}, }
]; ];
for (const options of buildOptions) { for (const options of buildOptions) {
@ -50,7 +75,6 @@ for (const options of buildOptions) {
} }
/* --- HELPLER FUNCTIONS --- */ /* --- HELPLER FUNCTIONS --- */
async function build(options) { async function build(options) {
@ -69,3 +93,10 @@ async function build(options) {
options.output.file.replace(`${pkgJson.name}-${pkgJson.version}.`, `${pkgJson.name}-latest.`) options.output.file.replace(`${pkgJson.name}-${pkgJson.version}.`, `${pkgJson.name}-latest.`)
); );
} }
function camelise(str) {
return str.replace(/-([a-z])/g,
function (m, w) {
return w.toUpperCase();
});
}

View File

@ -1,3 +1,7 @@
const _ZERO = BigInt(0);
const _ONE = BigInt(1);
const _TWO = BigInt(2);
/** /**
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0 * Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
* *
@ -5,68 +9,10 @@
* *
* @returns {bigint} the absolute value of a * @returns {bigint} the absolute value of a
*/ */
const abs = function (a) { function abs(a) {
a = BigInt(a); a = BigInt(a);
return (a >= BigInt(0)) ? a : -a; return (a >= _ZERO) ? 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). * @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -83,15 +29,15 @@ const toZn = function (a, n) {
* *
* @returns {egcdReturn} * @returns {egcdReturn}
*/ */
const eGcd = function (a, b) { function eGcd(a, b) {
a = BigInt(a); a = BigInt(a);
b = BigInt(b); b = BigInt(b);
let x = BigInt(0); let x = _ZERO;
let y = BigInt(1); let y = _ONE;
let u = BigInt(1); let u = _ONE;
let v = BigInt(0); let v = _ZERO;
while (a !== BigInt(0)) { while (a !== _ZERO) {
let q = b / a; let q = b / a;
let r = b % a; let r = b % a;
let m = x - (u * q); let m = x - (u * q);
@ -108,7 +54,52 @@ const eGcd = function (a, b) {
x: x, x: x,
y: y y: y
}; };
}; }
/**
* 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
*/
function gcd(a, b) {
a = abs(a);
b = abs(b);
let shift = _ZERO;
while (!((a | b) & _ONE)) {
a >>= _ONE;
b >>= _ONE;
shift++;
}
while (!(a & _ONE)) a >>= _ONE;
do {
while (!(b & _ONE)) b >>= _ONE;
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
*/
function lcm(a, b) {
a = BigInt(a);
b = BigInt(b);
return abs(a * b) / gcd(a, b);
}
/** /**
* Modular inverse. * Modular inverse.
@ -118,14 +109,14 @@ const eGcd = function (a, b) {
* *
* @returns {bigint} the inverse modulo n * @returns {bigint} the inverse modulo n
*/ */
const modInv = function (a, n) { function modInv(a, n) {
let egcd = eGcd(a, n); let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) { if (egcd.b !== _ONE) {
return null; // modular inverse does not exist return null; // modular inverse does not exist
} else { } else {
return toZn(egcd.x, n); return toZn(egcd.x, n);
} }
}; }
/** /**
* Modular exponentiation a**b mod n * Modular exponentiation a**b mod n
@ -135,20 +126,20 @@ const modInv = function (a, n) {
* *
* @returns {bigint} a**b mod n * @returns {bigint} a**b mod n
*/ */
const modPow = function (a, b, n) { function modPow(a, b, n) {
// See Knuth, volume 2, section 4.6.3. // See Knuth, volume 2, section 4.6.3.
n = BigInt(n); n = BigInt(n);
a = toZn(a, n); a = toZn(a, n);
b = BigInt(b); b = BigInt(b);
if (b < BigInt(0)) { if (b < _ZERO) {
return modInv(modPow(a, abs(b), n), n); return modInv(modPow(a, abs(b), n), n);
} }
let result = BigInt(1); let result = _ONE;
let x = a; let x = a;
while (b > 0) { while (b > 0) {
var leastSignificantBit = b % BigInt(2); var leastSignificantBit = b % _TWO;
b = b / BigInt(2); b = b / _TWO;
if (leastSignificantBit == BigInt(1)) { if (leastSignificantBit == _ONE) {
result = result * x; result = result * x;
result = result % n; result = result % n;
} }
@ -156,20 +147,19 @@ const modPow = function (a, b, n) {
x = x % n; x = x % n;
} }
return result; return result;
}; }
var main = { /**
abs: abs, * Finds the smallest positive element that is congruent to a in modulo n
gcd: gcd, * @param {number|bigint} a An integer
lcm: lcm, * @param {number|bigint} n The modulo
modInv: modInv, *
modPow: modPow * @returns {bigint} The smallest positive representation of a in modulo n
}; */
var main_1 = main.abs; function toZn(a, n) {
var main_2 = main.gcd; n = BigInt(n);
var main_3 = main.lcm; a = BigInt(a) % n;
var main_4 = main.modInv; return (a < 0) ? a + n : a;
var main_5 = main.modPow; }
export default main; export { abs, eGcd, gcd, lcm, modInv, modPow, toZn };
export { main_1 as abs, main_2 as gcd, main_3 as lcm, main_4 as modInv, main_5 as modPow };

View File

@ -1 +1 @@
const abs=function(b){return b=BigInt(b),b>=BigInt(0)?b:-b},gcd=function(c,d){c=abs(c),d=abs(d);let e=BigInt(0);for(;!((c|d)&BigInt(1));)c>>=BigInt(1),d>>=BigInt(1),e++;for(;!(c&BigInt(1));)c>>=BigInt(1);do{for(;!(d&BigInt(1));)d>>=BigInt(1);if(c>d){let a=c;c=d,d=a}d-=c}while(d);return c<<e},lcm=function(c,d){return c=BigInt(c),d=BigInt(d),abs(c*d)/gcd(c,d)},toZn=function(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b},eGcd=function(c,d){c=BigInt(c),d=BigInt(d);let e=BigInt(0),f=BigInt(1),g=BigInt(1),h=BigInt(0);for(;c!==BigInt(0);){let a=d/c,b=d%c,i=e-g*a,j=f-h*a;d=c,c=b,e=g,f=h,g=i,h=j}return{b:d,x:e,y:f}},modInv=function(b,a){let c=eGcd(b,a);return c.b===BigInt(1)?toZn(c.x,a):null},modPow=function(c,d,e){if(e=BigInt(e),c=toZn(c,e),d=BigInt(d),d<BigInt(0))return modInv(modPow(c,abs(d),e),e);let f=BigInt(1),g=c;for(;0<d;){var h=d%BigInt(2);d/=BigInt(2),h==BigInt(1)&&(f*=g,f%=e),g*=g,g%=e}return f};var main={abs:abs,gcd:gcd,lcm:lcm,modInv:modInv,modPow:modPow},main_1=main.abs,main_2=main.gcd,main_3=main.lcm,main_4=main.modInv,main_5=main.modPow;export default main;export{main_1 as abs,main_2 as gcd,main_3 as lcm,main_4 as modInv,main_5 as modPow}; const _ZERO=BigInt(0),_ONE=BigInt(1),_TWO=BigInt(2);function abs(b){return b=BigInt(b),b>=_ZERO?b:-b}function eGcd(c,d){c=BigInt(c),d=BigInt(d);let e=_ZERO,f=_ONE,g=_ONE,h=_ZERO;for(;c!==_ZERO;){let a=d/c,b=d%c,i=e-g*a,j=f-h*a;d=c,c=b,e=g,f=h,g=i,h=j}return{b:d,x:e,y:f}}function gcd(c,d){c=abs(c),d=abs(d);let e=_ZERO;for(;!((c|d)&_ONE);)c>>=_ONE,d>>=_ONE,e++;for(;!(c&_ONE);)c>>=_ONE;do{for(;!(d&_ONE);)d>>=_ONE;if(c>d){let a=c;c=d,d=a}d-=c}while(d);return c<<e}function lcm(c,d){return c=BigInt(c),d=BigInt(d),abs(c*d)/gcd(c,d)}function modInv(b,a){let c=eGcd(b,a);return c.b===_ONE?toZn(c.x,a):null}function modPow(c,d,e){if(e=BigInt(e),c=toZn(c,e),d=BigInt(d),d<_ZERO)return modInv(modPow(c,abs(d),e),e);let f=_ONE,g=c;for(;0<d;){var h=d%_TWO;d/=_TWO,h==_ONE&&(f*=g,f%=e),g*=g,g%=e}return f}function toZn(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b}export{abs,eGcd,gcd,lcm,modInv,modPow,toZn};

View File

@ -1,5 +1,11 @@
'use strict'; 'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const _ZERO = BigInt(0);
const _ONE = BigInt(1);
const _TWO = BigInt(2);
/** /**
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0 * Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
* *
@ -7,68 +13,10 @@
* *
* @returns {bigint} the absolute value of a * @returns {bigint} the absolute value of a
*/ */
const abs = function (a) { function abs(a) {
a = BigInt(a); a = BigInt(a);
return (a >= BigInt(0)) ? a : -a; return (a >= _ZERO) ? 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). * @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -85,15 +33,15 @@ const toZn = function (a, n) {
* *
* @returns {egcdReturn} * @returns {egcdReturn}
*/ */
const eGcd = function (a, b) { function eGcd(a, b) {
a = BigInt(a); a = BigInt(a);
b = BigInt(b); b = BigInt(b);
let x = BigInt(0); let x = _ZERO;
let y = BigInt(1); let y = _ONE;
let u = BigInt(1); let u = _ONE;
let v = BigInt(0); let v = _ZERO;
while (a !== BigInt(0)) { while (a !== _ZERO) {
let q = b / a; let q = b / a;
let r = b % a; let r = b % a;
let m = x - (u * q); let m = x - (u * q);
@ -110,7 +58,52 @@ const eGcd = function (a, b) {
x: x, x: x,
y: y y: y
}; };
}; }
/**
* 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
*/
function gcd(a, b) {
a = abs(a);
b = abs(b);
let shift = _ZERO;
while (!((a | b) & _ONE)) {
a >>= _ONE;
b >>= _ONE;
shift++;
}
while (!(a & _ONE)) a >>= _ONE;
do {
while (!(b & _ONE)) b >>= _ONE;
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
*/
function lcm(a, b) {
a = BigInt(a);
b = BigInt(b);
return abs(a * b) / gcd(a, b);
}
/** /**
* Modular inverse. * Modular inverse.
@ -120,14 +113,14 @@ const eGcd = function (a, b) {
* *
* @returns {bigint} the inverse modulo n * @returns {bigint} the inverse modulo n
*/ */
const modInv = function (a, n) { function modInv(a, n) {
let egcd = eGcd(a, n); let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) { if (egcd.b !== _ONE) {
return null; // modular inverse does not exist return null; // modular inverse does not exist
} else { } else {
return toZn(egcd.x, n); return toZn(egcd.x, n);
} }
}; }
/** /**
* Modular exponentiation a**b mod n * Modular exponentiation a**b mod n
@ -137,20 +130,20 @@ const modInv = function (a, n) {
* *
* @returns {bigint} a**b mod n * @returns {bigint} a**b mod n
*/ */
const modPow = function (a, b, n) { function modPow(a, b, n) {
// See Knuth, volume 2, section 4.6.3. // See Knuth, volume 2, section 4.6.3.
n = BigInt(n); n = BigInt(n);
a = toZn(a, n); a = toZn(a, n);
b = BigInt(b); b = BigInt(b);
if (b < BigInt(0)) { if (b < _ZERO) {
return modInv(modPow(a, abs(b), n), n); return modInv(modPow(a, abs(b), n), n);
} }
let result = BigInt(1); let result = _ONE;
let x = a; let x = a;
while (b > 0) { while (b > 0) {
var leastSignificantBit = b % BigInt(2); var leastSignificantBit = b % _TWO;
b = b / BigInt(2); b = b / _TWO;
if (leastSignificantBit == BigInt(1)) { if (leastSignificantBit == _ONE) {
result = result * x; result = result * x;
result = result % n; result = result % n;
} }
@ -158,12 +151,25 @@ const modPow = function (a, b, n) {
x = x % n; x = x % n;
} }
return result; return result;
}; }
module.exports = { /**
abs: abs, * Finds the smallest positive element that is congruent to a in modulo n
gcd: gcd, * @param {number|bigint} a An integer
lcm: lcm, * @param {number|bigint} n The modulo
modInv: modInv, *
modPow: modPow * @returns {bigint} The smallest positive representation of a in modulo n
}; */
function toZn(a, n) {
n = BigInt(n);
a = BigInt(a) % n;
return (a < 0) ? a + n : a;
}
exports.abs = abs;
exports.eGcd = eGcd;
exports.gcd = gcd;
exports.lcm = lcm;
exports.modInv = modInv;
exports.modPow = modPow;
exports.toZn = toZn;

34
package-lock.json generated
View File

@ -188,9 +188,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "11.13.0", "version": "11.13.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.7.tgz",
"integrity": "sha512-rx29MMkRdVmzunmiA4lzBYJNnXsW/PhG4kMBy2ATsYaDjGGR75dCFEVVROKpNwlVdcUX3xxlghKQOeDPBJobng==", "integrity": "sha512-suFHr6hcA9mp8vFrZTgrmqW2ZU3mbWsryQtQlY/QvwTISCw7nw/j+bCQPPohqmskhmqa5wLNuMHTTsc+xf1MQg==",
"dev": true "dev": true
}, },
"acorn": { "acorn": {
@ -774,9 +774,9 @@
} }
}, },
"commander": { "commander": {
"version": "2.19.0", "version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
@ -1169,9 +1169,9 @@
"dev": true "dev": true
}, },
"handlebars": { "handlebars": {
"version": "4.1.1", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
"integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
"dev": true, "dev": true,
"requires": { "requires": {
"neo-async": "^2.6.0", "neo-async": "^2.6.0",
@ -1891,13 +1891,13 @@
"dev": true "dev": true
}, },
"rollup": { "rollup": {
"version": "1.9.0", "version": "1.10.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.9.0.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.10.1.tgz",
"integrity": "sha512-cNZx9MLpKFMSaObdVFeu8nXw8gfw6yjuxWjt5mRCJcBZrAJ0NHAYwemKjayvYvhLaNNkf3+kS2DKRKS5J6NRVg==", "integrity": "sha512-pW353tmBE7QP622ITkGxtqF0d5gSRCVPD9xqM+fcPjudeZfoXMFW2sCzsTe2TU/zU1xamIjiS9xuFCPVT9fESw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/estree": "0.0.39", "@types/estree": "0.0.39",
"@types/node": "^11.13.0", "@types/node": "^11.13.5",
"acorn": "^6.1.1" "acorn": "^6.1.1"
} }
}, },
@ -2328,13 +2328,13 @@
"dev": true "dev": true
}, },
"uglify-js": { "uglify-js": {
"version": "3.4.10", "version": "3.5.8",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.8.tgz",
"integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", "integrity": "sha512-GFSjB1nZIzoIq70qvDRtWRORHX3vFkAnyK/rDExc0BN7r9+/S+Voz3t/fwJuVfjppAMz+ceR2poE7tkhvnVwQQ==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
"commander": "~2.19.0", "commander": "~2.20.0",
"source-map": "~0.6.1" "source-map": "~0.6.1"
} }
}, },

View File

@ -8,7 +8,9 @@
"lcm", "lcm",
"gcd", "gcd",
"egcd", "egcd",
"modinv",
"modular inverse", "modular inverse",
"modpow",
"modular exponentiation" "modular exponentiation"
], ],
"license": "MIT", "license": "MIT",
@ -26,13 +28,14 @@
"src": "./src" "src": "./src"
}, },
"scripts": { "scripts": {
"docs:build": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md",
"build": "node build/build.rollup.js", "build": "node build/build.rollup.js",
"prepublishOnly": "npm run build && npm run docs:build" "build:docs": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md",
"build:all": "npm run build && npm run build:docs",
"prepublishOnly": "npm run build && npm run build:docs"
}, },
"devDependencies": { "devDependencies": {
"jsdoc-to-markdown": "^4.0.1", "jsdoc-to-markdown": "^4.0.1",
"rollup": "^1.9.0", "rollup": "^1.10.1",
"rollup-plugin-babel-minify": "^8.0.0", "rollup-plugin-babel-minify": "^8.0.0",
"rollup-plugin-commonjs": "^9.3.4" "rollup-plugin-commonjs": "^9.3.4"
} }

View File

@ -1,5 +1,9 @@
'use strict'; 'use strict';
const _ZERO = BigInt(0);
const _ONE = BigInt(1);
const _TWO = BigInt(2);
/** /**
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0 * Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
* *
@ -7,68 +11,10 @@
* *
* @returns {bigint} the absolute value of a * @returns {bigint} the absolute value of a
*/ */
const abs = function (a) { export function abs(a) {
a = BigInt(a); a = BigInt(a);
return (a >= BigInt(0)) ? a : -a; return (a >= _ZERO) ? 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). * @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -85,15 +31,15 @@ const toZn = function (a, n) {
* *
* @returns {egcdReturn} * @returns {egcdReturn}
*/ */
const eGcd = function (a, b) { export function eGcd(a, b) {
a = BigInt(a); a = BigInt(a);
b = BigInt(b); b = BigInt(b);
let x = BigInt(0); let x = _ZERO;
let y = BigInt(1); let y = _ONE;
let u = BigInt(1); let u = _ONE;
let v = BigInt(0); let v = _ZERO;
while (a !== BigInt(0)) { while (a !== _ZERO) {
let q = b / a; let q = b / a;
let r = b % a; let r = b % a;
let m = x - (u * q); let m = x - (u * q);
@ -110,7 +56,52 @@ const eGcd = function (a, b) {
x: x, x: x,
y: y y: y
}; };
}; }
/**
* 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
*/
export function gcd(a, b) {
a = abs(a);
b = abs(b);
let shift = _ZERO;
while (!((a | b) & _ONE)) {
a >>= _ONE;
b >>= _ONE;
shift++;
}
while (!(a & _ONE)) a >>= _ONE;
do {
while (!(b & _ONE)) b >>= _ONE;
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
*/
export function lcm(a, b) {
a = BigInt(a);
b = BigInt(b);
return abs(a * b) / gcd(a, b);
}
/** /**
* Modular inverse. * Modular inverse.
@ -120,14 +111,14 @@ const eGcd = function (a, b) {
* *
* @returns {bigint} the inverse modulo n * @returns {bigint} the inverse modulo n
*/ */
const modInv = function (a, n) { export function modInv(a, n) {
let egcd = eGcd(a, n); let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) { if (egcd.b !== _ONE) {
return null; // modular inverse does not exist return null; // modular inverse does not exist
} else { } else {
return toZn(egcd.x, n); return toZn(egcd.x, n);
} }
}; }
/** /**
* Modular exponentiation a**b mod n * Modular exponentiation a**b mod n
@ -137,20 +128,20 @@ const modInv = function (a, n) {
* *
* @returns {bigint} a**b mod n * @returns {bigint} a**b mod n
*/ */
const modPow = function (a, b, n) { export function modPow(a, b, n) {
// See Knuth, volume 2, section 4.6.3. // See Knuth, volume 2, section 4.6.3.
n = BigInt(n); n = BigInt(n);
a = toZn(a, n); a = toZn(a, n);
b = BigInt(b); b = BigInt(b);
if (b < BigInt(0)) { if (b < _ZERO) {
return modInv(modPow(a, abs(b), n), n); return modInv(modPow(a, abs(b), n), n);
} }
let result = BigInt(1); let result = _ONE;
let x = a; let x = a;
while (b > 0) { while (b > 0) {
var leastSignificantBit = b % BigInt(2); var leastSignificantBit = b % _TWO;
b = b / BigInt(2); b = b / _TWO;
if (leastSignificantBit == BigInt(1)) { if (leastSignificantBit == _ONE) {
result = result * x; result = result * x;
result = result % n; result = result % n;
} }
@ -158,12 +149,17 @@ const modPow = function (a, b, n) {
x = x % n; x = x % n;
} }
return result; return result;
}; }
module.exports = { /**
abs: abs, * Finds the smallest positive element that is congruent to a in modulo n
gcd: gcd, * @param {number|bigint} a An integer
lcm: lcm, * @param {number|bigint} n The modulo
modInv: modInv, *
modPow: modPow * @returns {bigint} The smallest positive representation of a in modulo n
}; */
export function toZn(a, n) {
n = BigInt(n);
a = BigInt(a) % n;
return (a < 0) ? a + n : a;
}