Better code structure. Better README. Added generation of IIFE file-a
This commit is contained in:
parent
35197cb809
commit
68b8eebe8a
|
@ -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
|
||||
|
46
README.hbs
46
README.hbs
|
@ -1,62 +1,52 @@
|
|||
# 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
|
||||
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)**_
|
||||
|
||||
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).
|
||||
_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)._
|
||||
|
||||
## Installation
|
||||
bigint-mod-arith is distributed as both an ES6 and a CJS module.
|
||||
|
||||
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.
|
||||
|
||||
The CJS module is built as a standard node 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)
|
||||
as an ES6 module or an IIFE file; and for Node.js (>=10.4.0), as a CJS module.
|
||||
|
||||
bigint-mod-arith can be imported to your project with `npm`:
|
||||
```bash
|
||||
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).
|
||||
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.
|
||||
|
||||
## Usage examples
|
||||
## Usage example
|
||||
|
||||
With node js:
|
||||
```javascript
|
||||
const bigintModArith = require('bigint-mod-arith');
|
||||
|
||||
// Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
||||
// or the shorter no-linter-friendly new syntax 666n
|
||||
|
||||
/* Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
||||
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 b = BigInt('2');
|
||||
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';
|
||||
// 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 b = BigInt('2');
|
||||
|
|
116
README.md
116
README.md
|
@ -1,37 +1,52 @@
|
|||
# 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)**_
|
||||
|
||||
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).
|
||||
_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)._
|
||||
|
||||
## Installation
|
||||
bigint-mod-arith is distributed as both an ES6 and a CJS module.
|
||||
|
||||
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.
|
||||
|
||||
The CJS module is built as a standard node 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)
|
||||
as an ES6 module or an IIFE file; and for Node.js (>=10.4.0), as a CJS module.
|
||||
|
||||
bigint-mod-arith can be imported to your project with `npm`:
|
||||
```bash
|
||||
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:
|
||||
```html
|
||||
<script type="module" src="https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bigint-mod-arith-latest.browser.mod.min.js"></script>
|
||||
```
|
||||
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.
|
||||
|
||||
## Usage examples
|
||||
## Usage example
|
||||
|
||||
With node js:
|
||||
```javascript
|
||||
const bigintModArith = require('bigint-mod-arith');
|
||||
|
||||
// Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
||||
// or the shorter no-linter-friendly new syntax 666n
|
||||
/* Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
||||
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 b = BigInt('2');
|
||||
let n = BigInt('19');
|
||||
|
||||
console.log(bigintCryptoUtils.modPow(a, b, n)); // prints 6
|
||||
|
||||
console.log(bigintCryptoUtils.modInv(BigInt('2'), BigInt('5'))); // prints 3
|
||||
|
||||
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');
|
||||
|
@ -42,6 +57,7 @@ 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
|
||||
|
@ -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>
|
||||
<dd><p>Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0</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="#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>
|
||||
<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>
|
||||
<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>
|
||||
<dd><p>Modular inverse.</p>
|
||||
</dd>
|
||||
<dt><a href="#modPow">modPow(a, b, n)</a> ⇒ <code>bigint</code></dt>
|
||||
<dd><p>Modular exponentiation a**b mod n</p>
|
||||
</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>
|
||||
|
||||
## 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 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>
|
||||
|
||||
## 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> |
|
||||
| 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>
|
||||
|
||||
## modInv(a, n) ⇒ <code>bigint</code>
|
||||
|
@ -172,6 +175,19 @@ Modular exponentiation a**b mod n
|
|||
| b | <code>number</code> \| <code>bigint</code> | exponent |
|
||||
| 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>
|
||||
|
||||
## egcdReturn : <code>Object</code>
|
||||
|
|
|
@ -1,48 +1,73 @@
|
|||
'use strict';
|
||||
|
||||
const rollup = require('rollup');
|
||||
const commonjs = require('rollup-plugin-commonjs');
|
||||
const minify = require('rollup-plugin-babel-minify');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const pkgJson = require('../package.json');
|
||||
|
||||
const rootDir = path.join(__dirname, '..');
|
||||
const srcDir = path.join(rootDir, 'src');
|
||||
const dstDir = path.join(rootDir, 'dist');
|
||||
|
||||
const buildOptions = [
|
||||
{ // Browser
|
||||
input: {
|
||||
input: path.join(__dirname, '..', 'src', 'main.js'),
|
||||
plugins: [
|
||||
commonjs()
|
||||
],
|
||||
input: path.join(srcDir, 'main.js')
|
||||
},
|
||||
output: {
|
||||
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.browser.mod.js`),
|
||||
format: 'esm'
|
||||
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.browser.js`),
|
||||
format: 'iife',
|
||||
name: camelise(pkgJson.name)
|
||||
}
|
||||
},
|
||||
{ // Browser minified
|
||||
input: {
|
||||
input: path.join(__dirname, '..', 'src', 'main.js'),
|
||||
input: path.join(srcDir, 'main.js'),
|
||||
plugins: [
|
||||
commonjs(),
|
||||
minify({
|
||||
'comments': false
|
||||
})
|
||||
],
|
||||
},
|
||||
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'
|
||||
}
|
||||
},
|
||||
{ // Node
|
||||
input: {
|
||||
input: path.join(__dirname, '..', 'src', 'main.js'),
|
||||
input: path.join(srcDir, 'main.js'),
|
||||
},
|
||||
output: {
|
||||
file: path.join(__dirname, '..', 'dist', `${pkgJson.name}-${pkgJson.version}.node.js`),
|
||||
file: path.join(dstDir, `${pkgJson.name}-${pkgJson.version}.node.js`),
|
||||
format: 'cjs'
|
||||
}
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
for (const options of buildOptions) {
|
||||
|
@ -50,7 +75,6 @@ for (const options of buildOptions) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* --- HELPLER FUNCTIONS --- */
|
||||
|
||||
async function build(options) {
|
||||
|
@ -69,3 +93,10 @@ async function build(options) {
|
|||
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();
|
||||
});
|
||||
}
|
|
@ -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
|
||||
*
|
||||
|
@ -5,68 +9,10 @@
|
|||
*
|
||||
* @returns {bigint} the absolute value of a
|
||||
*/
|
||||
const abs = function (a) {
|
||||
function abs(a) {
|
||||
a = BigInt(a);
|
||||
return (a >= BigInt(0)) ? a : -a;
|
||||
};
|
||||
|
||||
/**
|
||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
||||
*
|
||||
* @param {number|bigint} a
|
||||
* @param {number|bigint} b
|
||||
*
|
||||
* @returns {bigint} The greatest common divisor of a and b
|
||||
*/
|
||||
const gcd = function (a, b) {
|
||||
a = abs(a);
|
||||
b = abs(b);
|
||||
let shift = BigInt(0);
|
||||
while (!((a | b) & BigInt(1))) {
|
||||
a >>= BigInt(1);
|
||||
b >>= BigInt(1);
|
||||
shift++;
|
||||
return (a >= _ZERO) ? a : -a;
|
||||
}
|
||||
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).
|
||||
|
@ -83,15 +29,15 @@ const toZn = function (a, n) {
|
|||
*
|
||||
* @returns {egcdReturn}
|
||||
*/
|
||||
const eGcd = function (a, b) {
|
||||
function eGcd(a, b) {
|
||||
a = BigInt(a);
|
||||
b = BigInt(b);
|
||||
let x = BigInt(0);
|
||||
let y = BigInt(1);
|
||||
let u = BigInt(1);
|
||||
let v = BigInt(0);
|
||||
let x = _ZERO;
|
||||
let y = _ONE;
|
||||
let u = _ONE;
|
||||
let v = _ZERO;
|
||||
|
||||
while (a !== BigInt(0)) {
|
||||
while (a !== _ZERO) {
|
||||
let q = b / a;
|
||||
let r = b % a;
|
||||
let m = x - (u * q);
|
||||
|
@ -108,7 +54,52 @@ const eGcd = function (a, b) {
|
|||
x: x,
|
||||
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.
|
||||
|
@ -118,14 +109,14 @@ const eGcd = function (a, b) {
|
|||
*
|
||||
* @returns {bigint} the inverse modulo n
|
||||
*/
|
||||
const modInv = function (a, n) {
|
||||
function modInv(a, n) {
|
||||
let egcd = eGcd(a, n);
|
||||
if (egcd.b !== BigInt(1)) {
|
||||
if (egcd.b !== _ONE) {
|
||||
return null; // modular inverse does not exist
|
||||
} else {
|
||||
return toZn(egcd.x, n);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Modular exponentiation a**b mod n
|
||||
|
@ -135,20 +126,20 @@ const modInv = function (a, 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.
|
||||
n = BigInt(n);
|
||||
a = toZn(a, n);
|
||||
b = BigInt(b);
|
||||
if (b < BigInt(0)) {
|
||||
if (b < _ZERO) {
|
||||
return modInv(modPow(a, abs(b), n), n);
|
||||
}
|
||||
let result = BigInt(1);
|
||||
let result = _ONE;
|
||||
let x = a;
|
||||
while (b > 0) {
|
||||
var leastSignificantBit = b % BigInt(2);
|
||||
b = b / BigInt(2);
|
||||
if (leastSignificantBit == BigInt(1)) {
|
||||
var leastSignificantBit = b % _TWO;
|
||||
b = b / _TWO;
|
||||
if (leastSignificantBit == _ONE) {
|
||||
result = result * x;
|
||||
result = result % n;
|
||||
}
|
||||
|
@ -156,20 +147,19 @@ const modPow = function (a, b, n) {
|
|||
x = x % n;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
var main = {
|
||||
abs: abs,
|
||||
gcd: gcd,
|
||||
lcm: lcm,
|
||||
modInv: modInv,
|
||||
modPow: modPow
|
||||
};
|
||||
var main_1 = main.abs;
|
||||
var main_2 = main.gcd;
|
||||
var main_3 = main.lcm;
|
||||
var main_4 = main.modInv;
|
||||
var main_5 = main.modPow;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function toZn(a, n) {
|
||||
n = BigInt(n);
|
||||
a = BigInt(a) % n;
|
||||
return (a < 0) ? a + n : a;
|
||||
}
|
||||
|
||||
export default main;
|
||||
export { main_1 as abs, main_2 as gcd, main_3 as lcm, main_4 as modInv, main_5 as modPow };
|
||||
export { abs, eGcd, gcd, lcm, modInv, modPow, toZn };
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
'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
|
||||
*
|
||||
|
@ -7,68 +13,10 @@
|
|||
*
|
||||
* @returns {bigint} the absolute value of a
|
||||
*/
|
||||
const abs = function (a) {
|
||||
function abs(a) {
|
||||
a = BigInt(a);
|
||||
return (a >= BigInt(0)) ? a : -a;
|
||||
};
|
||||
|
||||
/**
|
||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
||||
*
|
||||
* @param {number|bigint} a
|
||||
* @param {number|bigint} b
|
||||
*
|
||||
* @returns {bigint} The greatest common divisor of a and b
|
||||
*/
|
||||
const gcd = function (a, b) {
|
||||
a = abs(a);
|
||||
b = abs(b);
|
||||
let shift = BigInt(0);
|
||||
while (!((a | b) & BigInt(1))) {
|
||||
a >>= BigInt(1);
|
||||
b >>= BigInt(1);
|
||||
shift++;
|
||||
return (a >= _ZERO) ? a : -a;
|
||||
}
|
||||
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).
|
||||
|
@ -85,15 +33,15 @@ const toZn = function (a, n) {
|
|||
*
|
||||
* @returns {egcdReturn}
|
||||
*/
|
||||
const eGcd = function (a, b) {
|
||||
function eGcd(a, b) {
|
||||
a = BigInt(a);
|
||||
b = BigInt(b);
|
||||
let x = BigInt(0);
|
||||
let y = BigInt(1);
|
||||
let u = BigInt(1);
|
||||
let v = BigInt(0);
|
||||
let x = _ZERO;
|
||||
let y = _ONE;
|
||||
let u = _ONE;
|
||||
let v = _ZERO;
|
||||
|
||||
while (a !== BigInt(0)) {
|
||||
while (a !== _ZERO) {
|
||||
let q = b / a;
|
||||
let r = b % a;
|
||||
let m = x - (u * q);
|
||||
|
@ -110,7 +58,52 @@ const eGcd = function (a, b) {
|
|||
x: x,
|
||||
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.
|
||||
|
@ -120,14 +113,14 @@ const eGcd = function (a, b) {
|
|||
*
|
||||
* @returns {bigint} the inverse modulo n
|
||||
*/
|
||||
const modInv = function (a, n) {
|
||||
function modInv(a, n) {
|
||||
let egcd = eGcd(a, n);
|
||||
if (egcd.b !== BigInt(1)) {
|
||||
if (egcd.b !== _ONE) {
|
||||
return null; // modular inverse does not exist
|
||||
} else {
|
||||
return toZn(egcd.x, n);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Modular exponentiation a**b mod n
|
||||
|
@ -137,20 +130,20 @@ const modInv = function (a, 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.
|
||||
n = BigInt(n);
|
||||
a = toZn(a, n);
|
||||
b = BigInt(b);
|
||||
if (b < BigInt(0)) {
|
||||
if (b < _ZERO) {
|
||||
return modInv(modPow(a, abs(b), n), n);
|
||||
}
|
||||
let result = BigInt(1);
|
||||
let result = _ONE;
|
||||
let x = a;
|
||||
while (b > 0) {
|
||||
var leastSignificantBit = b % BigInt(2);
|
||||
b = b / BigInt(2);
|
||||
if (leastSignificantBit == BigInt(1)) {
|
||||
var leastSignificantBit = b % _TWO;
|
||||
b = b / _TWO;
|
||||
if (leastSignificantBit == _ONE) {
|
||||
result = result * x;
|
||||
result = result % n;
|
||||
}
|
||||
|
@ -158,12 +151,25 @@ const modPow = function (a, b, n) {
|
|||
x = x % n;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
abs: abs,
|
||||
gcd: gcd,
|
||||
lcm: lcm,
|
||||
modInv: modInv,
|
||||
modPow: modPow
|
||||
};
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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;
|
||||
|
|
|
@ -188,9 +188,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "11.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.0.tgz",
|
||||
"integrity": "sha512-rx29MMkRdVmzunmiA4lzBYJNnXsW/PhG4kMBy2ATsYaDjGGR75dCFEVVROKpNwlVdcUX3xxlghKQOeDPBJobng==",
|
||||
"version": "11.13.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.7.tgz",
|
||||
"integrity": "sha512-suFHr6hcA9mp8vFrZTgrmqW2ZU3mbWsryQtQlY/QvwTISCw7nw/j+bCQPPohqmskhmqa5wLNuMHTTsc+xf1MQg==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn": {
|
||||
|
@ -774,9 +774,9 @@
|
|||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
|
||||
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
|
||||
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
|
@ -1169,9 +1169,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz",
|
||||
"integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==",
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
|
||||
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"neo-async": "^2.6.0",
|
||||
|
@ -1891,13 +1891,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"rollup": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.9.0.tgz",
|
||||
"integrity": "sha512-cNZx9MLpKFMSaObdVFeu8nXw8gfw6yjuxWjt5mRCJcBZrAJ0NHAYwemKjayvYvhLaNNkf3+kS2DKRKS5J6NRVg==",
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.10.1.tgz",
|
||||
"integrity": "sha512-pW353tmBE7QP622ITkGxtqF0d5gSRCVPD9xqM+fcPjudeZfoXMFW2sCzsTe2TU/zU1xamIjiS9xuFCPVT9fESw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/estree": "0.0.39",
|
||||
"@types/node": "^11.13.0",
|
||||
"@types/node": "^11.13.5",
|
||||
"acorn": "^6.1.1"
|
||||
}
|
||||
},
|
||||
|
@ -2328,13 +2328,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.4.10",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
|
||||
"integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
|
||||
"version": "3.5.8",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.8.tgz",
|
||||
"integrity": "sha512-GFSjB1nZIzoIq70qvDRtWRORHX3vFkAnyK/rDExc0BN7r9+/S+Voz3t/fwJuVfjppAMz+ceR2poE7tkhvnVwQQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"commander": "~2.19.0",
|
||||
"commander": "~2.20.0",
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
"lcm",
|
||||
"gcd",
|
||||
"egcd",
|
||||
"modinv",
|
||||
"modular inverse",
|
||||
"modpow",
|
||||
"modular exponentiation"
|
||||
],
|
||||
"license": "MIT",
|
||||
|
@ -26,13 +28,14 @@
|
|||
"src": "./src"
|
||||
},
|
||||
"scripts": {
|
||||
"docs:build": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md",
|
||||
"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": {
|
||||
"jsdoc-to-markdown": "^4.0.1",
|
||||
"rollup": "^1.9.0",
|
||||
"rollup": "^1.10.1",
|
||||
"rollup-plugin-babel-minify": "^8.0.0",
|
||||
"rollup-plugin-commonjs": "^9.3.4"
|
||||
}
|
||||
|
|
164
src/main.js
164
src/main.js
|
@ -1,5 +1,9 @@
|
|||
'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
|
||||
*
|
||||
|
@ -7,68 +11,10 @@
|
|||
*
|
||||
* @returns {bigint} the absolute value of a
|
||||
*/
|
||||
const abs = function (a) {
|
||||
export function abs(a) {
|
||||
a = BigInt(a);
|
||||
return (a >= BigInt(0)) ? a : -a;
|
||||
};
|
||||
|
||||
/**
|
||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
||||
*
|
||||
* @param {number|bigint} a
|
||||
* @param {number|bigint} b
|
||||
*
|
||||
* @returns {bigint} The greatest common divisor of a and b
|
||||
*/
|
||||
const gcd = function (a, b) {
|
||||
a = abs(a);
|
||||
b = abs(b);
|
||||
let shift = BigInt(0);
|
||||
while (!((a | b) & BigInt(1))) {
|
||||
a >>= BigInt(1);
|
||||
b >>= BigInt(1);
|
||||
shift++;
|
||||
return (a >= _ZERO) ? a : -a;
|
||||
}
|
||||
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).
|
||||
|
@ -85,15 +31,15 @@ const toZn = function (a, n) {
|
|||
*
|
||||
* @returns {egcdReturn}
|
||||
*/
|
||||
const eGcd = function (a, b) {
|
||||
export function eGcd(a, b) {
|
||||
a = BigInt(a);
|
||||
b = BigInt(b);
|
||||
let x = BigInt(0);
|
||||
let y = BigInt(1);
|
||||
let u = BigInt(1);
|
||||
let v = BigInt(0);
|
||||
let x = _ZERO;
|
||||
let y = _ONE;
|
||||
let u = _ONE;
|
||||
let v = _ZERO;
|
||||
|
||||
while (a !== BigInt(0)) {
|
||||
while (a !== _ZERO) {
|
||||
let q = b / a;
|
||||
let r = b % a;
|
||||
let m = x - (u * q);
|
||||
|
@ -110,7 +56,52 @@ const eGcd = function (a, b) {
|
|||
x: x,
|
||||
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.
|
||||
|
@ -120,14 +111,14 @@ const eGcd = function (a, b) {
|
|||
*
|
||||
* @returns {bigint} the inverse modulo n
|
||||
*/
|
||||
const modInv = function (a, n) {
|
||||
export function modInv(a, n) {
|
||||
let egcd = eGcd(a, n);
|
||||
if (egcd.b !== BigInt(1)) {
|
||||
if (egcd.b !== _ONE) {
|
||||
return null; // modular inverse does not exist
|
||||
} else {
|
||||
return toZn(egcd.x, n);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Modular exponentiation a**b mod n
|
||||
|
@ -137,20 +128,20 @@ const modInv = function (a, 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.
|
||||
n = BigInt(n);
|
||||
a = toZn(a, n);
|
||||
b = BigInt(b);
|
||||
if (b < BigInt(0)) {
|
||||
if (b < _ZERO) {
|
||||
return modInv(modPow(a, abs(b), n), n);
|
||||
}
|
||||
let result = BigInt(1);
|
||||
let result = _ONE;
|
||||
let x = a;
|
||||
while (b > 0) {
|
||||
var leastSignificantBit = b % BigInt(2);
|
||||
b = b / BigInt(2);
|
||||
if (leastSignificantBit == BigInt(1)) {
|
||||
var leastSignificantBit = b % _TWO;
|
||||
b = b / _TWO;
|
||||
if (leastSignificantBit == _ONE) {
|
||||
result = result * x;
|
||||
result = result % n;
|
||||
}
|
||||
|
@ -158,12 +149,17 @@ const modPow = function (a, b, n) {
|
|||
x = x % n;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
abs: abs,
|
||||
gcd: gcd,
|
||||
lcm: lcm,
|
||||
modInv: modInv,
|
||||
modPow: modPow
|
||||
};
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export function toZn(a, n) {
|
||||
n = BigInt(n);
|
||||
a = BigInt(a) % n;
|
||||
return (a < 0) ? a + n : a;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue