aboutsummaryrefslogtreecommitdiff
path: root/node_modules/bn.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-03 15:35:00 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-03 15:35:00 +0200
commitde98e0b232509d5f40c135d540a70e415272ff85 (patch)
treea79222a5b58484ab3b80d18efcaaa7ccc4769b33 /node_modules/bn.js
parente0c9d480a73fa629c1e4a47d3e721f1d2d345406 (diff)
downloadwallet-core-de98e0b232509d5f40c135d540a70e415272ff85.tar.xz
node_modules
Diffstat (limited to 'node_modules/bn.js')
-rw-r--r--node_modules/bn.js/.npmignore6
-rw-r--r--node_modules/bn.js/.travis.yml15
-rw-r--r--node_modules/bn.js/README.md219
-rw-r--r--node_modules/bn.js/lib/bn.js3427
-rw-r--r--node_modules/bn.js/package.json33
-rw-r--r--node_modules/bn.js/test/arithmetic-test.js635
-rw-r--r--node_modules/bn.js/test/binary-test.js233
-rw-r--r--node_modules/bn.js/test/constructor-test.js149
-rw-r--r--node_modules/bn.js/test/fixtures.js264
-rw-r--r--node_modules/bn.js/test/pummel/dh-group-test.js23
-rw-r--r--node_modules/bn.js/test/red-test.js263
-rw-r--r--node_modules/bn.js/test/utils-test.js345
-rw-r--r--node_modules/bn.js/util/genCombMulTo.js65
-rw-r--r--node_modules/bn.js/util/genCombMulTo10.js65
14 files changed, 5742 insertions, 0 deletions
diff --git a/node_modules/bn.js/.npmignore b/node_modules/bn.js/.npmignore
new file mode 100644
index 000000000..6d1eebbd0
--- /dev/null
+++ b/node_modules/bn.js/.npmignore
@@ -0,0 +1,6 @@
+benchmarks/
+coverage/
+node_modules/
+npm-debug.log
+1.js
+logo.png
diff --git a/node_modules/bn.js/.travis.yml b/node_modules/bn.js/.travis.yml
new file mode 100644
index 000000000..936b7b787
--- /dev/null
+++ b/node_modules/bn.js/.travis.yml
@@ -0,0 +1,15 @@
+sudo: false
+language: node_js
+node_js:
+ - "0.10"
+ - "0.12"
+ - "4"
+ - "5"
+env:
+ matrix:
+ - TEST_SUITE=unit
+matrix:
+ include:
+ - node_js: "4"
+ env: TEST_SUITE=lint
+script: npm run $TEST_SUITE
diff --git a/node_modules/bn.js/README.md b/node_modules/bn.js/README.md
new file mode 100644
index 000000000..fee65baad
--- /dev/null
+++ b/node_modules/bn.js/README.md
@@ -0,0 +1,219 @@
+# <img src="./logo.png" alt="bn.js" width="160" height="160" />
+
+> BigNum in pure javascript
+
+[![Build Status](https://secure.travis-ci.org/indutny/bn.js.png)](http://travis-ci.org/indutny/bn.js)
+
+## Install
+`npm install --save bn.js`
+
+## Usage
+
+```js
+const BN = require('bn.js');
+
+var a = new BN('dead', 16);
+var b = new BN('101010', 2);
+
+var res = a.add(b);
+console.log(res.toString(10)); // 57047
+```
+
+**Note**: decimals are not supported in this library.
+
+## Notation
+
+### Prefixes
+
+There are several prefixes to instructions that affect the way the work. Here
+is the list of them in the order of appearance in the function name:
+
+* `i` - perform operation in-place, storing the result in the host object (on
+ which the method was invoked). Might be used to avoid number allocation costs
+* `u` - unsigned, ignore the sign of operands when performing operation, or
+ always return positive value. Second case applies to reduction operations
+ like `mod()`. In such cases if the result will be negative - modulo will be
+ added to the result to make it positive
+
+### Postfixes
+
+The only available postfix at the moment is:
+
+* `n` - which means that the argument of the function must be a plain JavaScript
+ number
+
+### Examples
+
+* `a.iadd(b)` - perform addition on `a` and `b`, storing the result in `a`
+* `a.pmod(b)` - reduce `a` modulo `b`, returning positive value
+* `a.iushln(13)` - shift bits of `a` left by 13
+
+## Instructions
+
+Prefixes/postfixes are put in parens at the of the line. `endian` - could be
+either `le` (little-endian) or `be` (big-endian).
+
+### Utilities
+
+* `a.clone()` - clone number
+* `a.toString(base, length)` - convert to base-string and pad with zeroes
+* `a.toNumber()` - convert to Javascript Number (limited to 53 bits)
+* `a.toJSON()` - convert to JSON compatible hex string (alias of `toString(16)`)
+* `a.toArray(endian, length)` - convert to byte `Array`, and optionally zero
+ pad to length, throwing if already exceeding
+* `a.toArrayLike(type, endian, length)` - convert to an instance of `type`,
+ which must behave like an `Array`
+* `a.toBuffer(endian, length)` - convert to Node.js Buffer (if available)
+* `a.bitLength()` - get number of bits occupied
+* `a.zeroBits()` - return number of less-significant consequent zero bits
+ (example: `1010000` has 4 zero bits)
+* `a.byteLength()` - return number of bytes occupied
+* `a.isNeg()` - true if the number is negative
+* `a.isEven()` - no comments
+* `a.isOdd()` - no comments
+* `a.isZero()` - no comments
+* `a.cmp(b)` - compare numbers and return `-1` (a `<` b), `0` (a `==` b), or `1` (a `>` b)
+ depending on the comparison result (`ucmp`, `cmpn`)
+* `a.lt(b)` - `a` less than `b` (`n`)
+* `a.lte(b)` - `a` less than or equals `b` (`n`)
+* `a.gt(b)` - `a` greater than `b` (`n`)
+* `a.gte(b)` - `a` greater than or equals `b` (`n`)
+* `a.eq(b)` - `a` equals `b` (`n`)
+* `a.toTwos(width)` - convert to two's complement representation, where `width` is bit width
+* `a.fromTwos(width)` - convert from two's complement representation, where `width` is the bit width
+* `a.isBN(object)` - returns true if the supplied `object` is a BN.js instance
+
+### Arithmetics
+
+* `a.neg()` - negate sign (`i`)
+* `a.abs()` - absolute value (`i`)
+* `a.add(b)` - addition (`i`, `n`, `in`)
+* `a.sub(b)` - subtraction (`i`, `n`, `in`)
+* `a.mul(b)` - multiply (`i`, `n`, `in`)
+* `a.sqr()` - square (`i`)
+* `a.pow(b)` - raise `a` to the power of `b`
+* `a.div(b)` - divide (`divn`, `idivn`)
+* `a.mod(b)` - reduct (`u`, `n`) (but no `umodn`)
+* `a.divRound(b)` - rounded division
+
+### Bit operations
+
+* `a.or(b)` - or (`i`, `u`, `iu`)
+* `a.and(b)` - and (`i`, `u`, `iu`, `andln`) (NOTE: `andln` is going to be replaced
+ with `andn` in future)
+* `a.xor(b)` - xor (`i`, `u`, `iu`)
+* `a.setn(b)` - set specified bit to `1`
+* `a.shln(b)` - shift left (`i`, `u`, `iu`)
+* `a.shrn(b)` - shift right (`i`, `u`, `iu`)
+* `a.testn(b)` - test if specified bit is set
+* `a.maskn(b)` - clear bits with indexes higher or equal to `b` (`i`)
+* `a.bincn(b)` - add `1 << b` to the number
+* `a.notn(w)` - not (for the width specified by `w`) (`i`)
+
+### Reduction
+
+* `a.gcd(b)` - GCD
+* `a.egcd(b)` - Extended GCD results (`{ a: ..., b: ..., gcd: ... }`)
+* `a.invm(b)` - inverse `a` modulo `b`
+
+## Fast reduction
+
+When doing lots of reductions using the same modulo, it might be beneficial to
+use some tricks: like [Montgomery multiplication][0], or using special algorithm
+for [Mersenne Prime][1].
+
+### Reduction context
+
+To enable this tricks one should create a reduction context:
+
+```js
+var red = BN.red(num);
+```
+where `num` is just a BN instance.
+
+Or:
+
+```js
+var red = BN.red(primeName);
+```
+
+Where `primeName` is either of these [Mersenne Primes][1]:
+
+* `'k256'`
+* `'p224'`
+* `'p192'`
+* `'p25519'`
+
+Or:
+
+```js
+var red = BN.mont(num);
+```
+
+To reduce numbers with [Montgomery trick][1]. `.mont()` is generally faster than
+`.red(num)`, but slower than `BN.red(primeName)`.
+
+### Converting numbers
+
+Before performing anything in reduction context - numbers should be converted
+to it. Usually, this means that one should:
+
+* Convert inputs to reducted ones
+* Operate on them in reduction context
+* Convert outputs back from the reduction context
+
+Here is how one may convert numbers to `red`:
+
+```js
+var redA = a.toRed(red);
+```
+Where `red` is a reduction context created using instructions above
+
+Here is how to convert them back:
+
+```js
+var a = redA.fromRed();
+```
+
+### Red instructions
+
+Most of the instructions from the very start of this readme have their
+counterparts in red context:
+
+* `a.redAdd(b)`, `a.redIAdd(b)`
+* `a.redSub(b)`, `a.redISub(b)`
+* `a.redShl(num)`
+* `a.redMul(b)`, `a.redIMul(b)`
+* `a.redSqr()`, `a.redISqr()`
+* `a.redSqrt()` - square root modulo reduction context's prime
+* `a.redInvm()` - modular inverse of the number
+* `a.redNeg()`
+* `a.redPow(b)` - modular exponentiation
+
+## LICENSE
+
+This software is licensed under the MIT License.
+
+Copyright Fedor Indutny, 2015.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+[0]: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
+[1]: https://en.wikipedia.org/wiki/Mersenne_prime
diff --git a/node_modules/bn.js/lib/bn.js b/node_modules/bn.js/lib/bn.js
new file mode 100644
index 000000000..29a4c51a8
--- /dev/null
+++ b/node_modules/bn.js/lib/bn.js
@@ -0,0 +1,3427 @@
+(function (module, exports) {
+ 'use strict';
+
+ // Utils
+ function assert (val, msg) {
+ if (!val) throw new Error(msg || 'Assertion failed');
+ }
+
+ // Could use `inherits` module, but don't want to move from single file
+ // architecture yet.
+ function inherits (ctor, superCtor) {
+ ctor.super_ = superCtor;
+ var TempCtor = function () {};
+ TempCtor.prototype = superCtor.prototype;
+ ctor.prototype = new TempCtor();
+ ctor.prototype.constructor = ctor;
+ }
+
+ // BN
+
+ function BN (number, base, endian) {
+ if (BN.isBN(number)) {
+ return number;
+ }
+
+ this.negative = 0;
+ this.words = null;
+ this.length = 0;
+
+ // Reduction context
+ this.red = null;
+
+ if (number !== null) {
+ if (base === 'le' || base === 'be') {
+ endian = base;
+ base = 10;
+ }
+
+ this._init(number || 0, base || 10, endian || 'be');
+ }
+ }
+ if (typeof module === 'object') {
+ module.exports = BN;
+ } else {
+ exports.BN = BN;
+ }
+
+ BN.BN = BN;
+ BN.wordSize = 26;
+
+ var Buffer;
+ try {
+ Buffer = require('buf' + 'fer').Buffer;
+ } catch (e) {
+ }
+
+ BN.isBN = function isBN (num) {
+ if (num instanceof BN) {
+ return true;
+ }
+
+ return num !== null && typeof num === 'object' &&
+ num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
+ };
+
+ BN.max = function max (left, right) {
+ if (left.cmp(right) > 0) return left;
+ return right;
+ };
+
+ BN.min = function min (left, right) {
+ if (left.cmp(right) < 0) return left;
+ return right;
+ };
+
+ BN.prototype._init = function init (number, base, endian) {
+ if (typeof number === 'number') {
+ return this._initNumber(number, base, endian);
+ }
+
+ if (typeof number === 'object') {
+ return this._initArray(number, base, endian);
+ }
+
+ if (base === 'hex') {
+ base = 16;
+ }
+ assert(base === (base | 0) && base >= 2 && base <= 36);
+
+ number = number.toString().replace(/\s+/g, '');
+ var start = 0;
+ if (number[0] === '-') {
+ start++;
+ }
+
+ if (base === 16) {
+ this._parseHex(number, start);
+ } else {
+ this._parseBase(number, base, start);
+ }
+
+ if (number[0] === '-') {
+ this.negative = 1;
+ }
+
+ this.strip();
+
+ if (endian !== 'le') return;
+
+ this._initArray(this.toArray(), base, endian);
+ };
+
+ BN.prototype._initNumber = function _initNumber (number, base, endian) {
+ if (number < 0) {
+ this.negative = 1;
+ number = -number;
+ }
+ if (number < 0x4000000) {
+ this.words = [ number & 0x3ffffff ];
+ this.length = 1;
+ } else if (number < 0x10000000000000) {
+ this.words = [
+ number & 0x3ffffff,
+ (number / 0x4000000) & 0x3ffffff
+ ];
+ this.length = 2;
+ } else {
+ assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
+ this.words = [
+ number & 0x3ffffff,
+ (number / 0x4000000) & 0x3ffffff,
+ 1
+ ];
+ this.length = 3;
+ }
+
+ if (endian !== 'le') return;
+
+ // Reverse the bytes
+ this._initArray(this.toArray(), base, endian);
+ };
+
+ BN.prototype._initArray = function _initArray (number, base, endian) {
+ // Perhaps a Uint8Array
+ assert(typeof number.length === 'number');
+ if (number.length <= 0) {
+ this.words = [ 0 ];
+ this.length = 1;
+ return this;
+ }
+
+ this.length = Math.ceil(number.length / 3);
+ this.words = new Array(this.length);
+ for (var i = 0; i < this.length; i++) {
+ this.words[i] = 0;
+ }
+
+ var j, w;
+ var off = 0;
+ if (endian === 'be') {
+ for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
+ w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
+ this.words[j] |= (w << off) & 0x3ffffff;
+ this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
+ off += 24;
+ if (off >= 26) {
+ off -= 26;
+ j++;
+ }
+ }
+ } else if (endian === 'le') {
+ for (i = 0, j = 0; i < number.length; i += 3) {
+ w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
+ this.words[j] |= (w << off) & 0x3ffffff;
+ this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
+ off += 24;
+ if (off >= 26) {
+ off -= 26;
+ j++;
+ }
+ }
+ }
+ return this.strip();
+ };
+
+ function parseHex (str, start, end) {
+ var r = 0;
+ var len = Math.min(str.length, end);
+ for (var i = start; i < len; i++) {
+ var c = str.charCodeAt(i) - 48;
+
+ r <<= 4;
+
+ // 'a' - 'f'
+ if (c >= 49 && c <= 54) {
+ r |= c - 49 + 0xa;
+
+ // 'A' - 'F'
+ } else if (c >= 17 && c <= 22) {
+ r |= c - 17 + 0xa;
+
+ // '0' - '9'
+ } else {
+ r |= c & 0xf;
+ }
+ }
+ return r;
+ }
+
+ BN.prototype._parseHex = function _parseHex (number, start) {
+ // Create possibly bigger array to ensure that it fits the number
+ this.length = Math.ceil((number.length - start) / 6);
+ this.words = new Array(this.length);
+ for (var i = 0; i < this.length; i++) {
+ this.words[i] = 0;
+ }
+
+ var j, w;
+ // Scan 24-bit chunks and add them to the number
+ var off = 0;
+ for (i = number.length - 6, j = 0; i >= start; i -= 6) {
+ w = parseHex(number, i, i + 6);
+ this.words[j] |= (w << off) & 0x3ffffff;
+ // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb
+ this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
+ off += 24;
+ if (off >= 26) {
+ off -= 26;
+ j++;
+ }
+ }
+ if (i + 6 !== start) {
+ w = parseHex(number, start, i + 6);
+ this.words[j] |= (w << off) & 0x3ffffff;
+ this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
+ }
+ this.strip();
+ };
+
+ function parseBase (str, start, end, mul) {
+ var r = 0;
+ var len = Math.min(str.length, end);
+ for (var i = start; i < len; i++) {
+ var c = str.charCodeAt(i) - 48;
+
+ r *= mul;
+
+ // 'a'
+ if (c >= 49) {
+ r += c - 49 + 0xa;
+
+ // 'A'
+ } else if (c >= 17) {
+ r += c - 17 + 0xa;
+
+ // '0' - '9'
+ } else {
+ r += c;
+ }
+ }
+ return r;
+ }
+
+ BN.prototype._parseBase = function _parseBase (number, base, start) {
+ // Initialize as zero
+ this.words = [ 0 ];
+ this.length = 1;
+
+ // Find length of limb in base
+ for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
+ limbLen++;
+ }
+ limbLen--;
+ limbPow = (limbPow / base) | 0;
+
+ var total = number.length - start;
+ var mod = total % limbLen;
+ var end = Math.min(total, total - mod) + start;
+
+ var word = 0;
+ for (var i = start; i < end; i += limbLen) {
+ word = parseBase(number, i, i + limbLen, base);
+
+ this.imuln(limbPow);
+ if (this.words[0] + word < 0x4000000) {
+ this.words[0] += word;
+ } else {
+ this._iaddn(word);
+ }
+ }
+
+ if (mod !== 0) {
+ var pow = 1;
+ word = parseBase(number, i, number.length, base);
+
+ for (i = 0; i < mod; i++) {
+ pow *= base;
+ }
+
+ this.imuln(pow);
+ if (this.words[0] + word < 0x4000000) {
+ this.words[0] += word;
+ } else {
+ this._iaddn(word);
+ }
+ }
+ };
+
+ BN.prototype.copy = function copy (dest) {
+ dest.words = new Array(this.length);
+ for (var i = 0; i < this.length; i++) {
+ dest.words[i] = this.words[i];
+ }
+ dest.length = this.length;
+ dest.negative = this.negative;
+ dest.red = this.red;
+ };
+
+ BN.prototype.clone = function clone () {
+ var r = new BN(null);
+ this.copy(r);
+ return r;
+ };
+
+ BN.prototype._expand = function _expand (size) {
+ while (this.length < size) {
+ this.words[this.length++] = 0;
+ }
+ return this;
+ };
+
+ // Remove leading `0` from `this`
+ BN.prototype.strip = function strip () {
+ while (this.length > 1 && this.words[this.length - 1] === 0) {
+ this.length--;
+ }
+ return this._normSign();
+ };
+
+ BN.prototype._normSign = function _normSign () {
+ // -0 = 0
+ if (this.length === 1 && this.words[0] === 0) {
+ this.negative = 0;
+ }
+ return this;
+ };
+
+ BN.prototype.inspect = function inspect () {
+ return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
+ };
+
+ /*
+
+ var zeros = [];
+ var groupSizes = [];
+ var groupBases = [];
+
+ var s = '';
+ var i = -1;
+ while (++i < BN.wordSize) {
+ zeros[i] = s;
+ s += '0';
+ }
+ groupSizes[0] = 0;
+ groupSizes[1] = 0;
+ groupBases[0] = 0;
+ groupBases[1] = 0;
+ var base = 2 - 1;
+ while (++base < 36 + 1) {
+ var groupSize = 0;
+ var groupBase = 1;
+ while (groupBase < (1 << BN.wordSize) / base) {
+ groupBase *= base;
+ groupSize += 1;
+ }
+ groupSizes[base] = groupSize;
+ groupBases[base] = groupBase;
+ }
+
+ */
+
+ var zeros = [
+ '',
+ '0',
+ '00',
+ '000',
+ '0000',
+ '00000',
+ '000000',
+ '0000000',
+ '00000000',
+ '000000000',
+ '0000000000',
+ '00000000000',
+ '000000000000',
+ '0000000000000',
+ '00000000000000',
+ '000000000000000',
+ '0000000000000000',
+ '00000000000000000',
+ '000000000000000000',
+ '0000000000000000000',
+ '00000000000000000000',
+ '000000000000000000000',
+ '0000000000000000000000',
+ '00000000000000000000000',
+ '000000000000000000000000',
+ '0000000000000000000000000'
+ ];
+
+ var groupSizes = [
+ 0, 0,
+ 25, 16, 12, 11, 10, 9, 8,
+ 8, 7, 7, 7, 7, 6, 6,
+ 6, 6, 6, 6, 6, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5
+ ];
+
+ var groupBases = [
+ 0, 0,
+ 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
+ 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
+ 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
+ 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
+ 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
+ ];
+
+ BN.prototype.toString = function toString (base, padding) {
+ base = base || 10;
+ padding = padding | 0 || 1;
+
+ var out;
+ if (base === 16 || base === 'hex') {
+ out = '';
+ var off = 0;
+ var carry = 0;
+ for (var i = 0; i < this.length; i++) {
+ var w = this.words[i];
+ var word = (((w << off) | carry) & 0xffffff).toString(16);
+ carry = (w >>> (24 - off)) & 0xffffff;
+ if (carry !== 0 || i !== this.length - 1) {
+ out = zeros[6 - word.length] + word + out;
+ } else {
+ out = word + out;
+ }
+ off += 2;
+ if (off >= 26) {
+ off -= 26;
+ i--;
+ }
+ }
+ if (carry !== 0) {
+ out = carry.toString(16) + out;
+ }
+ while (out.length % padding !== 0) {
+ out = '0' + out;
+ }
+ if (this.negative !== 0) {
+ out = '-' + out;
+ }
+ return out;
+ }
+
+ if (base === (base | 0) && base >= 2 && base <= 36) {
+ // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
+ var groupSize = groupSizes[base];
+ // var groupBase = Math.pow(base, groupSize);
+ var groupBase = groupBases[base];
+ out = '';
+ var c = this.clone();
+ c.negative = 0;
+ while (!c.isZero()) {
+ var r = c.modn(groupBase).toString(base);
+ c = c.idivn(groupBase);
+
+ if (!c.isZero()) {
+ out = zeros[groupSize - r.length] + r + out;
+ } else {
+ out = r + out;
+ }
+ }
+ if (this.isZero()) {
+ out = '0' + out;
+ }
+ while (out.length % padding !== 0) {
+ out = '0' + out;
+ }
+ if (this.negative !== 0) {
+ out = '-' + out;
+ }
+ return out;
+ }
+
+ assert(false, 'Base should be between 2 and 36');
+ };
+
+ BN.prototype.toNumber = function toNumber () {
+ var ret = this.words[0];
+ if (this.length === 2) {
+ ret += this.words[1] * 0x4000000;
+ } else if (this.length === 3 && this.words[2] === 0x01) {
+ // NOTE: at this stage it is known that the top bit is set
+ ret += 0x10000000000000 + (this.words[1] * 0x4000000);
+ } else if (this.length > 2) {
+ assert(false, 'Number can only safely store up to 53 bits');
+ }
+ return (this.negative !== 0) ? -ret : ret;
+ };
+
+ BN.prototype.toJSON = function toJSON () {
+ return this.toString(16);
+ };
+
+ BN.prototype.toBuffer = function toBuffer (endian, length) {
+ assert(typeof Buffer !== 'undefined');
+ return this.toArrayLike(Buffer, endian, length);
+ };
+
+ BN.prototype.toArray = function toArray (endian, length) {
+ return this.toArrayLike(Array, endian, length);
+ };
+
+ BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
+ var byteLength = this.byteLength();
+ var reqLength = length || Math.max(1, byteLength);
+ assert(byteLength <= reqLength, 'byte array longer than desired length');
+ assert(reqLength > 0, 'Requested array length <= 0');
+
+ this.strip();
+ var littleEndian = endian === 'le';
+ var res = new ArrayType(reqLength);
+
+ var b, i;
+ var q = this.clone();
+ if (!littleEndian) {
+ // Assume big-endian
+ for (i = 0; i < reqLength - byteLength; i++) {
+ res[i] = 0;
+ }
+
+ for (i = 0; !q.isZero(); i++) {
+ b = q.andln(0xff);
+ q.iushrn(8);
+
+ res[reqLength - i - 1] = b;
+ }
+ } else {
+ for (i = 0; !q.isZero(); i++) {
+ b = q.andln(0xff);
+ q.iushrn(8);
+
+ res[i] = b;
+ }
+
+ for (; i < reqLength; i++) {
+ res[i] = 0;
+ }
+ }
+
+ return res;
+ };
+
+ if (Math.clz32) {
+ BN.prototype._countBits = function _countBits (w) {
+ return 32 - Math.clz32(w);
+ };
+ } else {
+ BN.prototype._countBits = function _countBits (w) {
+ var t = w;
+ var r = 0;
+ if (t >= 0x1000) {
+ r += 13;
+ t >>>= 13;
+ }
+ if (t >= 0x40) {
+ r += 7;
+ t >>>= 7;
+ }
+ if (t >= 0x8) {
+ r += 4;
+ t >>>= 4;
+ }
+ if (t >= 0x02) {
+ r += 2;
+ t >>>= 2;
+ }
+ return r + t;
+ };
+ }
+
+ BN.prototype._zeroBits = function _zeroBits (w) {
+ // Short-cut
+ if (w === 0) return 26;
+
+ var t = w;
+ var r = 0;
+ if ((t & 0x1fff) === 0) {
+ r += 13;
+ t >>>= 13;
+ }
+ if ((t & 0x7f) === 0) {
+ r += 7;
+ t >>>= 7;
+ }
+ if ((t & 0xf) === 0) {
+ r += 4;
+ t >>>= 4;
+ }
+ if ((t & 0x3) === 0) {
+ r += 2;
+ t >>>= 2;
+ }
+ if ((t & 0x1) === 0) {
+ r++;
+ }
+ return r;
+ };
+
+ // Return number of used bits in a BN
+ BN.prototype.bitLength = function bitLength () {
+ var w = this.words[this.length - 1];
+ var hi = this._countBits(w);
+ return (this.length - 1) * 26 + hi;
+ };
+
+ function toBitArray (num) {
+ var w = new Array(num.bitLength());
+
+ for (var bit = 0; bit < w.length; bit++) {
+ var off = (bit / 26) | 0;
+ var wbit = bit % 26;
+
+ w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
+ }
+
+ return w;
+ }
+
+ // Number of trailing zero bits
+ BN.prototype.zeroBits = function zeroBits () {
+ if (this.isZero()) return 0;
+
+ var r = 0;
+ for (var i = 0; i < this.length; i++) {
+ var b = this._zeroBits(this.words[i]);
+ r += b;
+ if (b !== 26) break;
+ }
+ return r;
+ };
+
+ BN.prototype.byteLength = function byteLength () {
+ return Math.ceil(this.bitLength() / 8);
+ };
+
+ BN.prototype.toTwos = function toTwos (width) {
+ if (this.negative !== 0) {
+ return this.abs().inotn(width).iaddn(1);
+ }
+ return this.clone();
+ };
+
+ BN.prototype.fromTwos = function fromTwos (width) {
+ if (this.testn(width - 1)) {
+ return this.notn(width).iaddn(1).ineg();
+ }
+ return this.clone();
+ };
+
+ BN.prototype.isNeg = function isNeg () {
+ return this.negative !== 0;
+ };
+
+ // Return negative clone of `this`
+ BN.prototype.neg = function neg () {
+ return this.clone().ineg();
+ };
+
+ BN.prototype.ineg = function ineg () {
+ if (!this.isZero()) {
+ this.negative ^= 1;
+ }
+
+ return this;
+ };
+
+ // Or `num` with `this` in-place
+ BN.prototype.iuor = function iuor (num) {
+ while (this.length < num.length) {
+ this.words[this.length++] = 0;
+ }
+
+ for (var i = 0; i < num.length; i++) {
+ this.words[i] = this.words[i] | num.words[i];
+ }
+
+ return this.strip();
+ };
+
+ BN.prototype.ior = function ior (num) {
+ assert((this.negative | num.negative) === 0);
+ return this.iuor(num);
+ };
+
+ // Or `num` with `this`
+ BN.prototype.or = function or (num) {
+ if (this.length > num.length) return this.clone().ior(num);
+ return num.clone().ior(this);
+ };
+
+ BN.prototype.uor = function uor (num) {
+ if (this.length > num.length) return this.clone().iuor(num);
+ return num.clone().iuor(this);
+ };
+
+ // And `num` with `this` in-place
+ BN.prototype.iuand = function iuand (num) {
+ // b = min-length(num, this)
+ var b;
+ if (this.length > num.length) {
+ b = num;
+ } else {
+ b = this;
+ }
+
+ for (var i = 0; i < b.length; i++) {
+ this.words[i] = this.words[i] & num.words[i];
+ }
+
+ this.length = b.length;
+
+ return this.strip();
+ };
+
+ BN.prototype.iand = function iand (num) {
+ assert((this.negative | num.negative) === 0);
+ return this.iuand(num);
+ };
+
+ // And `num` with `this`
+ BN.prototype.and = function and (num) {
+ if (this.length > num.length) return this.clone().iand(num);
+ return num.clone().iand(this);
+ };
+
+ BN.prototype.uand = function uand (num) {
+ if (this.length > num.length) return this.clone().iuand(num);
+ return num.clone().iuand(this);
+ };
+
+ // Xor `num` with `this` in-place
+ BN.prototype.iuxor = function iuxor (num) {
+ // a.length > b.length
+ var a;
+ var b;
+ if (this.length > num.length) {
+ a = this;
+ b = num;
+ } else {
+ a = num;
+ b = this;
+ }
+
+ for (var i = 0; i < b.length; i++) {
+ this.words[i] = a.words[i] ^ b.words[i];
+ }
+
+ if (this !== a) {
+ for (; i < a.length; i++) {
+ this.words[i] = a.words[i];
+ }
+ }
+
+ this.length = a.length;
+
+ return this.strip();
+ };
+
+ BN.prototype.ixor = function ixor (num) {
+ assert((this.negative | num.negative) === 0);
+ return this.iuxor(num);
+ };
+
+ // Xor `num` with `this`
+ BN.prototype.xor = function xor (num) {
+ if (this.length > num.length) return this.clone().ixor(num);
+ return num.clone().ixor(this);
+ };
+
+ BN.prototype.uxor = function uxor (num) {
+ if (this.length > num.length) return this.clone().iuxor(num);
+ return num.clone().iuxor(this);
+ };
+
+ // Not ``this`` with ``width`` bitwidth
+ BN.prototype.inotn = function inotn (width) {
+ assert(typeof width === 'number' && width >= 0);
+
+ var bytesNeeded = Math.ceil(width / 26) | 0;
+ var bitsLeft = width % 26;
+
+ // Extend the buffer with leading zeroes
+ this._expand(bytesNeeded);
+
+ if (bitsLeft > 0) {
+ bytesNeeded--;
+ }
+
+ // Handle complete words
+ for (var i = 0; i < bytesNeeded; i++) {
+ this.words[i] = ~this.words[i] & 0x3ffffff;
+ }
+
+ // Handle the residue
+ if (bitsLeft > 0) {
+ this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
+ }
+
+ // And remove leading zeroes
+ return this.strip();
+ };
+
+ BN.prototype.notn = function notn (width) {
+ return this.clone().inotn(width);
+ };
+
+ // Set `bit` of `this`
+ BN.prototype.setn = function setn (bit, val) {
+ assert(typeof bit === 'number' && bit >= 0);
+
+ var off = (bit / 26) | 0;
+ var wbit = bit % 26;
+
+ this._expand(off + 1);
+
+ if (val) {
+ this.words[off] = this.words[off] | (1 << wbit);
+ } else {
+ this.words[off] = this.words[off] & ~(1 << wbit);
+ }
+
+ return this.strip();
+ };
+
+ // Add `num` to `this` in-place
+ BN.prototype.iadd = function iadd (num) {
+ var r;
+
+ // negative + positive
+ if (this.negative !== 0 && num.negative === 0) {
+ this.negative = 0;
+ r = this.isub(num);
+ this.negative ^= 1;
+ return this._normSign();
+
+ // positive + negative
+ } else if (this.negative === 0 && num.negative !== 0) {
+ num.negative = 0;
+ r = this.isub(num);
+ num.negative = 1;
+ return r._normSign();
+ }
+
+ // a.length > b.length
+ var a, b;
+ if (this.length > num.length) {
+ a = this;
+ b = num;
+ } else {
+ a = num;
+ b = this;
+ }
+
+ var carry = 0;
+ for (var i = 0; i < b.length; i++) {
+ r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
+ this.words[i] = r & 0x3ffffff;
+ carry = r >>> 26;
+ }
+ for (; carry !== 0 && i < a.length; i++) {
+ r = (a.words[i] | 0) + carry;
+ this.words[i] = r & 0x3ffffff;
+ carry = r >>> 26;
+ }
+
+ this.length = a.length;
+ if (carry !== 0) {
+ this.words[this.length] = carry;
+ this.length++;
+ // Copy the rest of the words
+ } else if (a !== this) {
+ for (; i < a.length; i++) {
+ this.words[i] = a.words[i];
+ }
+ }
+
+ return this;
+ };
+
+ // Add `num` to `this`
+ BN.prototype.add = function add (num) {
+ var res;
+ if (num.negative !== 0 && this.negative === 0) {
+ num.negative = 0;
+ res = this.sub(num);
+ num.negative ^= 1;
+ return res;
+ } else if (num.negative === 0 && this.negative !== 0) {
+ this.negative = 0;
+ res = num.sub(this);
+ this.negative = 1;
+ return res;
+ }
+
+ if (this.length > num.length) return this.clone().iadd(num);
+
+ return num.clone().iadd(this);
+ };
+
+ // Subtract `num` from `this` in-place
+ BN.prototype.isub = function isub (num) {
+ // this - (-num) = this + num
+ if (num.negative !== 0) {
+ num.negative = 0;
+ var r = this.iadd(num);
+ num.negative = 1;
+ return r._normSign();
+
+ // -this - num = -(this + num)
+ } else if (this.negative !== 0) {
+ this.negative = 0;
+ this.iadd(num);
+ this.negative = 1;
+ return this._normSign();
+ }
+
+ // At this point both numbers are positive
+ var cmp = this.cmp(num);
+
+ // Optimization - zeroify
+ if (cmp === 0) {
+ this.negative = 0;
+ this.length = 1;
+ this.words[0] = 0;
+ return this;
+ }
+
+ // a > b
+ var a, b;
+ if (cmp > 0) {
+ a = this;
+ b = num;
+ } else {
+ a = num;
+ b = this;
+ }
+
+ var carry = 0;
+ for (var i = 0; i < b.length; i++) {
+ r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
+ carry = r >> 26;
+ this.words[i] = r & 0x3ffffff;
+ }
+ for (; carry !== 0 && i < a.length; i++) {
+ r = (a.words[i] | 0) + carry;
+ carry = r >> 26;
+ this.words[i] = r & 0x3ffffff;
+ }
+
+ // Copy rest of the words
+ if (carry === 0 && i < a.length && a !== this) {
+ for (; i < a.length; i++) {
+ this.words[i] = a.words[i];
+ }
+ }
+
+ this.length = Math.max(this.length, i);
+
+ if (a !== this) {
+ this.negative = 1;
+ }
+
+ return this.strip();
+ };
+
+ // Subtract `num` from `this`
+ BN.prototype.sub = function sub (num) {
+ return this.clone().isub(num);
+ };
+
+ function smallMulTo (self, num, out) {
+ out.negative = num.negative ^ self.negative;
+ var len = (self.length + num.length) | 0;
+ out.length = len;
+ len = (len - 1) | 0;
+
+ // Peel one iteration (compiler can't do it, because of code complexity)
+ var a = self.words[0] | 0;
+ var b = num.words[0] | 0;
+ var r = a * b;
+
+ var lo = r & 0x3ffffff;
+ var carry = (r / 0x4000000) | 0;
+ out.words[0] = lo;
+
+ for (var k = 1; k < len; k++) {
+ // Sum all words with the same `i + j = k` and accumulate `ncarry`,
+ // note that ncarry could be >= 0x3ffffff
+ var ncarry = carry >>> 26;
+ var rword = carry & 0x3ffffff;
+ var maxJ = Math.min(k, num.length - 1);
+ for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
+ var i = (k - j) | 0;
+ a = self.words[i] | 0;
+ b = num.words[j] | 0;
+ r = a * b + rword;
+ ncarry += (r / 0x4000000) | 0;
+ rword = r & 0x3ffffff;
+ }
+ out.words[k] = rword | 0;
+ carry = ncarry | 0;
+ }
+ if (carry !== 0) {
+ out.words[k] = carry | 0;
+ } else {
+ out.length--;
+ }
+
+ return out.strip();
+ }
+
+ // TODO(indutny): it may be reasonable to omit it for users who don't need
+ // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
+ // multiplication (like elliptic secp256k1).
+ var comb10MulTo = function comb10MulTo (self, num, out) {
+ var a = self.words;
+ var b = num.words;
+ var o = out.words;
+ var c = 0;
+ var lo;
+ var mid;
+ var hi;
+ var a0 = a[0] | 0;
+ var al0 = a0 & 0x1fff;
+ var ah0 = a0 >>> 13;
+ var a1 = a[1] | 0;
+ var al1 = a1 & 0x1fff;
+ var ah1 = a1 >>> 13;
+ var a2 = a[2] | 0;
+ var al2 = a2 & 0x1fff;
+ var ah2 = a2 >>> 13;
+ var a3 = a[3] | 0;
+ var al3 = a3 & 0x1fff;
+ var ah3 = a3 >>> 13;
+ var a4 = a[4] | 0;
+ var al4 = a4 & 0x1fff;
+ var ah4 = a4 >>> 13;
+ var a5 = a[5] | 0;
+ var al5 = a5 & 0x1fff;
+ var ah5 = a5 >>> 13;
+ var a6 = a[6] | 0;
+ var al6 = a6 & 0x1fff;
+ var ah6 = a6 >>> 13;
+ var a7 = a[7] | 0;
+ var al7 = a7 & 0x1fff;
+ var ah7 = a7 >>> 13;
+ var a8 = a[8] | 0;
+ var al8 = a8 & 0x1fff;
+ var ah8 = a8 >>> 13;
+ var a9 = a[9] | 0;
+ var al9 = a9 & 0x1fff;
+ var ah9 = a9 >>> 13;
+ var b0 = b[0] | 0;
+ var bl0 = b0 & 0x1fff;
+ var bh0 = b0 >>> 13;
+ var b1 = b[1] | 0;
+ var bl1 = b1 & 0x1fff;
+ var bh1 = b1 >>> 13;
+ var b2 = b[2] | 0;
+ var bl2 = b2 & 0x1fff;
+ var bh2 = b2 >>> 13;
+ var b3 = b[3] | 0;
+ var bl3 = b3 & 0x1fff;
+ var bh3 = b3 >>> 13;
+ var b4 = b[4] | 0;
+ var bl4 = b4 & 0x1fff;
+ var bh4 = b4 >>> 13;
+ var b5 = b[5] | 0;
+ var bl5 = b5 & 0x1fff;
+ var bh5 = b5 >>> 13;
+ var b6 = b[6] | 0;
+ var bl6 = b6 & 0x1fff;
+ var bh6 = b6 >>> 13;
+ var b7 = b[7] | 0;
+ var bl7 = b7 & 0x1fff;
+ var bh7 = b7 >>> 13;
+ var b8 = b[8] | 0;
+ var bl8 = b8 & 0x1fff;
+ var bh8 = b8 >>> 13;
+ var b9 = b[9] | 0;
+ var bl9 = b9 & 0x1fff;
+ var bh9 = b9 >>> 13;
+
+ out.negative = self.negative ^ num.negative;
+ out.length = 19;
+ /* k = 0 */
+ lo = Math.imul(al0, bl0);
+ mid = Math.imul(al0, bh0);
+ mid = (mid + Math.imul(ah0, bl0)) | 0;
+ hi = Math.imul(ah0, bh0);
+ var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
+ w0 &= 0x3ffffff;
+ /* k = 1 */
+ lo = Math.imul(al1, bl0);
+ mid = Math.imul(al1, bh0);
+ mid = (mid + Math.imul(ah1, bl0)) | 0;
+ hi = Math.imul(ah1, bh0);
+ lo = (lo + Math.imul(al0, bl1)) | 0;
+ mid = (mid + Math.imul(al0, bh1)) | 0;
+ mid = (mid + Math.imul(ah0, bl1)) | 0;
+ hi = (hi + Math.imul(ah0, bh1)) | 0;
+ var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
+ w1 &= 0x3ffffff;
+ /* k = 2 */
+ lo = Math.imul(al2, bl0);
+ mid = Math.imul(al2, bh0);
+ mid = (mid + Math.imul(ah2, bl0)) | 0;
+ hi = Math.imul(ah2, bh0);
+ lo = (lo + Math.imul(al1, bl1)) | 0;
+ mid = (mid + Math.imul(al1, bh1)) | 0;
+ mid = (mid + Math.imul(ah1, bl1)) | 0;
+ hi = (hi + Math.imul(ah1, bh1)) | 0;
+ lo = (lo + Math.imul(al0, bl2)) | 0;
+ mid = (mid + Math.imul(al0, bh2)) | 0;
+ mid = (mid + Math.imul(ah0, bl2)) | 0;
+ hi = (hi + Math.imul(ah0, bh2)) | 0;
+ var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
+ w2 &= 0x3ffffff;
+ /* k = 3 */
+ lo = Math.imul(al3, bl0);
+ mid = Math.imul(al3, bh0);
+ mid = (mid + Math.imul(ah3, bl0)) | 0;
+ hi = Math.imul(ah3, bh0);
+ lo = (lo + Math.imul(al2, bl1)) | 0;
+ mid = (mid + Math.imul(al2, bh1)) | 0;
+ mid = (mid + Math.imul(ah2, bl1)) | 0;
+ hi = (hi + Math.imul(ah2, bh1)) | 0;
+ lo = (lo + Math.imul(al1, bl2)) | 0;
+ mid = (mid + Math.imul(al1, bh2)) | 0;
+ mid = (mid + Math.imul(ah1, bl2)) | 0;
+ hi = (hi + Math.imul(ah1, bh2)) | 0;
+ lo = (lo + Math.imul(al0, bl3)) | 0;
+ mid = (mid + Math.imul(al0, bh3)) | 0;
+ mid = (mid + Math.imul(ah0, bl3)) | 0;
+ hi = (hi + Math.imul(ah0, bh3)) | 0;
+ var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
+ w3 &= 0x3ffffff;
+ /* k = 4 */
+ lo = Math.imul(al4, bl0);
+ mid = Math.imul(al4, bh0);
+ mid = (mid + Math.imul(ah4, bl0)) | 0;
+ hi = Math.imul(ah4, bh0);
+ lo = (lo + Math.imul(al3, bl1)) | 0;
+ mid = (mid + Math.imul(al3, bh1)) | 0;
+ mid = (mid + Math.imul(ah3, bl1)) | 0;
+ hi = (hi + Math.imul(ah3, bh1)) | 0;
+ lo = (lo + Math.imul(al2, bl2)) | 0;
+ mid = (mid + Math.imul(al2, bh2)) | 0;
+ mid = (mid + Math.imul(ah2, bl2)) | 0;
+ hi = (hi + Math.imul(ah2, bh2)) | 0;
+ lo = (lo + Math.imul(al1, bl3)) | 0;
+ mid = (mid + Math.imul(al1, bh3)) | 0;
+ mid = (mid + Math.imul(ah1, bl3)) | 0;
+ hi = (hi + Math.imul(ah1, bh3)) | 0;
+ lo = (lo + Math.imul(al0, bl4)) | 0;
+ mid = (mid + Math.imul(al0, bh4)) | 0;
+ mid = (mid + Math.imul(ah0, bl4)) | 0;
+ hi = (hi + Math.imul(ah0, bh4)) | 0;
+ var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
+ w4 &= 0x3ffffff;
+ /* k = 5 */
+ lo = Math.imul(al5, bl0);
+ mid = Math.imul(al5, bh0);
+ mid = (mid + Math.imul(ah5, bl0)) | 0;
+ hi = Math.imul(ah5, bh0);
+ lo = (lo + Math.imul(al4, bl1)) | 0;
+ mid = (mid + Math.imul(al4, bh1)) | 0;
+ mid = (mid + Math.imul(ah4, bl1)) | 0;
+ hi = (hi + Math.imul(ah4, bh1)) | 0;
+ lo = (lo + Math.imul(al3, bl2)) | 0;
+ mid = (mid + Math.imul(al3, bh2)) | 0;
+ mid = (mid + Math.imul(ah3, bl2)) | 0;
+ hi = (hi + Math.imul(ah3, bh2)) | 0;
+ lo = (lo + Math.imul(al2, bl3)) | 0;
+ mid = (mid + Math.imul(al2, bh3)) | 0;
+ mid = (mid + Math.imul(ah2, bl3)) | 0;
+ hi = (hi + Math.imul(ah2, bh3)) | 0;
+ lo = (lo + Math.imul(al1, bl4)) | 0;
+ mid = (mid + Math.imul(al1, bh4)) | 0;
+ mid = (mid + Math.imul(ah1, bl4)) | 0;
+ hi = (hi + Math.imul(ah1, bh4)) | 0;
+ lo = (lo + Math.imul(al0, bl5)) | 0;
+ mid = (mid + Math.imul(al0, bh5)) | 0;
+ mid = (mid + Math.imul(ah0, bl5)) | 0;
+ hi = (hi + Math.imul(ah0, bh5)) | 0;
+ var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
+ w5 &= 0x3ffffff;
+ /* k = 6 */
+ lo = Math.imul(al6, bl0);
+ mid = Math.imul(al6, bh0);
+ mid = (mid + Math.imul(ah6, bl0)) | 0;
+ hi = Math.imul(ah6, bh0);
+ lo = (lo + Math.imul(al5, bl1)) | 0;
+ mid = (mid + Math.imul(al5, bh1)) | 0;
+ mid = (mid + Math.imul(ah5, bl1)) | 0;
+ hi = (hi + Math.imul(ah5, bh1)) | 0;
+ lo = (lo + Math.imul(al4, bl2)) | 0;
+ mid = (mid + Math.imul(al4, bh2)) | 0;
+ mid = (mid + Math.imul(ah4, bl2)) | 0;
+ hi = (hi + Math.imul(ah4, bh2)) | 0;
+ lo = (lo + Math.imul(al3, bl3)) | 0;
+ mid = (mid + Math.imul(al3, bh3)) | 0;
+ mid = (mid + Math.imul(ah3, bl3)) | 0;
+ hi = (hi + Math.imul(ah3, bh3)) | 0;
+ lo = (lo + Math.imul(al2, bl4)) | 0;
+ mid = (mid + Math.imul(al2, bh4)) | 0;
+ mid = (mid + Math.imul(ah2, bl4)) | 0;
+ hi = (hi + Math.imul(ah2, bh4)) | 0;
+ lo = (lo + Math.imul(al1, bl5)) | 0;
+ mid = (mid + Math.imul(al1, bh5)) | 0;
+ mid = (mid + Math.imul(ah1, bl5)) | 0;
+ hi = (hi + Math.imul(ah1, bh5)) | 0;
+ lo = (lo + Math.imul(al0, bl6)) | 0;
+ mid = (mid + Math.imul(al0, bh6)) | 0;
+ mid = (mid + Math.imul(ah0, bl6)) | 0;
+ hi = (hi + Math.imul(ah0, bh6)) | 0;
+ var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
+ w6 &= 0x3ffffff;
+ /* k = 7 */
+ lo = Math.imul(al7, bl0);
+ mid = Math.imul(al7, bh0);
+ mid = (mid + Math.imul(ah7, bl0)) | 0;
+ hi = Math.imul(ah7, bh0);
+ lo = (lo + Math.imul(al6, bl1)) | 0;
+ mid = (mid + Math.imul(al6, bh1)) | 0;
+ mid = (mid + Math.imul(ah6, bl1)) | 0;
+ hi = (hi + Math.imul(ah6, bh1)) | 0;
+ lo = (lo + Math.imul(al5, bl2)) | 0;
+ mid = (mid + Math.imul(al5, bh2)) | 0;
+ mid = (mid + Math.imul(ah5, bl2)) | 0;
+ hi = (hi + Math.imul(ah5, bh2)) | 0;
+ lo = (lo + Math.imul(al4, bl3)) | 0;
+ mid = (mid + Math.imul(al4, bh3)) | 0;
+ mid = (mid + Math.imul(ah4, bl3)) | 0;
+ hi = (hi + Math.imul(ah4, bh3)) | 0;
+ lo = (lo + Math.imul(al3, bl4)) | 0;
+ mid = (mid + Math.imul(al3, bh4)) | 0;
+ mid = (mid + Math.imul(ah3, bl4)) | 0;
+ hi = (hi + Math.imul(ah3, bh4)) | 0;
+ lo = (lo + Math.imul(al2, bl5)) | 0;
+ mid = (mid + Math.imul(al2, bh5)) | 0;
+ mid = (mid + Math.imul(ah2, bl5)) | 0;
+ hi = (hi + Math.imul(ah2, bh5)) | 0;
+ lo = (lo + Math.imul(al1, bl6)) | 0;
+ mid = (mid + Math.imul(al1, bh6)) | 0;
+ mid = (mid + Math.imul(ah1, bl6)) | 0;
+ hi = (hi + Math.imul(ah1, bh6)) | 0;
+ lo = (lo + Math.imul(al0, bl7)) | 0;
+ mid = (mid + Math.imul(al0, bh7)) | 0;
+ mid = (mid + Math.imul(ah0, bl7)) | 0;
+ hi = (hi + Math.imul(ah0, bh7)) | 0;
+ var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
+ w7 &= 0x3ffffff;
+ /* k = 8 */
+ lo = Math.imul(al8, bl0);
+ mid = Math.imul(al8, bh0);
+ mid = (mid + Math.imul(ah8, bl0)) | 0;
+ hi = Math.imul(ah8, bh0);
+ lo = (lo + Math.imul(al7, bl1)) | 0;
+ mid = (mid + Math.imul(al7, bh1)) | 0;
+ mid = (mid + Math.imul(ah7, bl1)) | 0;
+ hi = (hi + Math.imul(ah7, bh1)) | 0;
+ lo = (lo + Math.imul(al6, bl2)) | 0;
+ mid = (mid + Math.imul(al6, bh2)) | 0;
+ mid = (mid + Math.imul(ah6, bl2)) | 0;
+ hi = (hi + Math.imul(ah6, bh2)) | 0;
+ lo = (lo + Math.imul(al5, bl3)) | 0;
+ mid = (mid + Math.imul(al5, bh3)) | 0;
+ mid = (mid + Math.imul(ah5, bl3)) | 0;
+ hi = (hi + Math.imul(ah5, bh3)) | 0;
+ lo = (lo + Math.imul(al4, bl4)) | 0;
+ mid = (mid + Math.imul(al4, bh4)) | 0;
+ mid = (mid + Math.imul(ah4, bl4)) | 0;
+ hi = (hi + Math.imul(ah4, bh4)) | 0;
+ lo = (lo + Math.imul(al3, bl5)) | 0;
+ mid = (mid + Math.imul(al3, bh5)) | 0;
+ mid = (mid + Math.imul(ah3, bl5)) | 0;
+ hi = (hi + Math.imul(ah3, bh5)) | 0;
+ lo = (lo + Math.imul(al2, bl6)) | 0;
+ mid = (mid + Math.imul(al2, bh6)) | 0;
+ mid = (mid + Math.imul(ah2, bl6)) | 0;
+ hi = (hi + Math.imul(ah2, bh6)) | 0;
+ lo = (lo + Math.imul(al1, bl7)) | 0;
+ mid = (mid + Math.imul(al1, bh7)) | 0;
+ mid = (mid + Math.imul(ah1, bl7)) | 0;
+ hi = (hi + Math.imul(ah1, bh7)) | 0;
+ lo = (lo + Math.imul(al0, bl8)) | 0;
+ mid = (mid + Math.imul(al0, bh8)) | 0;
+ mid = (mid + Math.imul(ah0, bl8)) | 0;
+ hi = (hi + Math.imul(ah0, bh8)) | 0;
+ var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
+ w8 &= 0x3ffffff;
+ /* k = 9 */
+ lo = Math.imul(al9, bl0);
+ mid = Math.imul(al9, bh0);
+ mid = (mid + Math.imul(ah9, bl0)) | 0;
+ hi = Math.imul(ah9, bh0);
+ lo = (lo + Math.imul(al8, bl1)) | 0;
+ mid = (mid + Math.imul(al8, bh1)) | 0;
+ mid = (mid + Math.imul(ah8, bl1)) | 0;
+ hi = (hi + Math.imul(ah8, bh1)) | 0;
+ lo = (lo + Math.imul(al7, bl2)) | 0;
+ mid = (mid + Math.imul(al7, bh2)) | 0;
+ mid = (mid + Math.imul(ah7, bl2)) | 0;
+ hi = (hi + Math.imul(ah7, bh2)) | 0;
+ lo = (lo + Math.imul(al6, bl3)) | 0;
+ mid = (mid + Math.imul(al6, bh3)) | 0;
+ mid = (mid + Math.imul(ah6, bl3)) | 0;
+ hi = (hi + Math.imul(ah6, bh3)) | 0;
+ lo = (lo + Math.imul(al5, bl4)) | 0;
+ mid = (mid + Math.imul(al5, bh4)) | 0;
+ mid = (mid + Math.imul(ah5, bl4)) | 0;
+ hi = (hi + Math.imul(ah5, bh4)) | 0;
+ lo = (lo + Math.imul(al4, bl5)) | 0;
+ mid = (mid + Math.imul(al4, bh5)) | 0;
+ mid = (mid + Math.imul(ah4, bl5)) | 0;
+ hi = (hi + Math.imul(ah4, bh5)) | 0;
+ lo = (lo + Math.imul(al3, bl6)) | 0;
+ mid = (mid + Math.imul(al3, bh6)) | 0;
+ mid = (mid + Math.imul(ah3, bl6)) | 0;
+ hi = (hi + Math.imul(ah3, bh6)) | 0;
+ lo = (lo + Math.imul(al2, bl7)) | 0;
+ mid = (mid + Math.imul(al2, bh7)) | 0;
+ mid = (mid + Math.imul(ah2, bl7)) | 0;
+ hi = (hi + Math.imul(ah2, bh7)) | 0;
+ lo = (lo + Math.imul(al1, bl8)) | 0;
+ mid = (mid + Math.imul(al1, bh8)) | 0;
+ mid = (mid + Math.imul(ah1, bl8)) | 0;
+ hi = (hi + Math.imul(ah1, bh8)) | 0;
+ lo = (lo + Math.imul(al0, bl9)) | 0;
+ mid = (mid + Math.imul(al0, bh9)) | 0;
+ mid = (mid + Math.imul(ah0, bl9)) | 0;
+ hi = (hi + Math.imul(ah0, bh9)) | 0;
+ var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
+ w9 &= 0x3ffffff;
+ /* k = 10 */
+ lo = Math.imul(al9, bl1);
+ mid = Math.imul(al9, bh1);
+ mid = (mid + Math.imul(ah9, bl1)) | 0;
+ hi = Math.imul(ah9, bh1);
+ lo = (lo + Math.imul(al8, bl2)) | 0;
+ mid = (mid + Math.imul(al8, bh2)) | 0;
+ mid = (mid + Math.imul(ah8, bl2)) | 0;
+ hi = (hi + Math.imul(ah8, bh2)) | 0;
+ lo = (lo + Math.imul(al7, bl3)) | 0;
+ mid = (mid + Math.imul(al7, bh3)) | 0;
+ mid = (mid + Math.imul(ah7, bl3)) | 0;
+ hi = (hi + Math.imul(ah7, bh3)) | 0;
+ lo = (lo + Math.imul(al6, bl4)) | 0;
+ mid = (mid + Math.imul(al6, bh4)) | 0;
+ mid = (mid + Math.imul(ah6, bl4)) | 0;
+ hi = (hi + Math.imul(ah6, bh4)) | 0;
+ lo = (lo + Math.imul(al5, bl5)) | 0;
+ mid = (mid + Math.imul(al5, bh5)) | 0;
+ mid = (mid + Math.imul(ah5, bl5)) | 0;
+ hi = (hi + Math.imul(ah5, bh5)) | 0;
+ lo = (lo + Math.imul(al4, bl6)) | 0;
+ mid = (mid + Math.imul(al4, bh6)) | 0;
+ mid = (mid + Math.imul(ah4, bl6)) | 0;
+ hi = (hi + Math.imul(ah4, bh6)) | 0;
+ lo = (lo + Math.imul(al3, bl7)) | 0;
+ mid = (mid + Math.imul(al3, bh7)) | 0;
+ mid = (mid + Math.imul(ah3, bl7)) | 0;
+ hi = (hi + Math.imul(ah3, bh7)) | 0;
+ lo = (lo + Math.imul(al2, bl8)) | 0;
+ mid = (mid + Math.imul(al2, bh8)) | 0;
+ mid = (mid + Math.imul(ah2, bl8)) | 0;
+ hi = (hi + Math.imul(ah2, bh8)) | 0;
+ lo = (lo + Math.imul(al1, bl9)) | 0;
+ mid = (mid + Math.imul(al1, bh9)) | 0;
+ mid = (mid + Math.imul(ah1, bl9)) | 0;
+ hi = (hi + Math.imul(ah1, bh9)) | 0;
+ var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
+ w10 &= 0x3ffffff;
+ /* k = 11 */
+ lo = Math.imul(al9, bl2);
+ mid = Math.imul(al9, bh2);
+ mid = (mid + Math.imul(ah9, bl2)) | 0;
+ hi = Math.imul(ah9, bh2);
+ lo = (lo + Math.imul(al8, bl3)) | 0;
+ mid = (mid + Math.imul(al8, bh3)) | 0;
+ mid = (mid + Math.imul(ah8, bl3)) | 0;
+ hi = (hi + Math.imul(ah8, bh3)) | 0;
+ lo = (lo + Math.imul(al7, bl4)) | 0;
+ mid = (mid + Math.imul(al7, bh4)) | 0;
+ mid = (mid + Math.imul(ah7, bl4)) | 0;
+ hi = (hi + Math.imul(ah7, bh4)) | 0;
+ lo = (lo + Math.imul(al6, bl5)) | 0;
+ mid = (mid + Math.imul(al6, bh5)) | 0;
+ mid = (mid + Math.imul(ah6, bl5)) | 0;
+ hi = (hi + Math.imul(ah6, bh5)) | 0;
+ lo = (lo + Math.imul(al5, bl6)) | 0;
+ mid = (mid + Math.imul(al5, bh6)) | 0;
+ mid = (mid + Math.imul(ah5, bl6)) | 0;
+ hi = (hi + Math.imul(ah5, bh6)) | 0;
+ lo = (lo + Math.imul(al4, bl7)) | 0;
+ mid = (mid + Math.imul(al4, bh7)) | 0;
+ mid = (mid + Math.imul(ah4, bl7)) | 0;
+ hi = (hi + Math.imul(ah4, bh7)) | 0;
+ lo = (lo + Math.imul(al3, bl8)) | 0;
+ mid = (mid + Math.imul(al3, bh8)) | 0;
+ mid = (mid + Math.imul(ah3, bl8)) | 0;
+ hi = (hi + Math.imul(ah3, bh8)) | 0;
+ lo = (lo + Math.imul(al2, bl9)) | 0;
+ mid = (mid + Math.imul(al2, bh9)) | 0;
+ mid = (mid + Math.imul(ah2, bl9)) | 0;
+ hi = (hi + Math.imul(ah2, bh9)) | 0;
+ var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
+ w11 &= 0x3ffffff;
+ /* k = 12 */
+ lo = Math.imul(al9, bl3);
+ mid = Math.imul(al9, bh3);
+ mid = (mid + Math.imul(ah9, bl3)) | 0;
+ hi = Math.imul(ah9, bh3);
+ lo = (lo + Math.imul(al8, bl4)) | 0;
+ mid = (mid + Math.imul(al8, bh4)) | 0;
+ mid = (mid + Math.imul(ah8, bl4)) | 0;
+ hi = (hi + Math.imul(ah8, bh4)) | 0;
+ lo = (lo + Math.imul(al7, bl5)) | 0;
+ mid = (mid + Math.imul(al7, bh5)) | 0;
+ mid = (mid + Math.imul(ah7, bl5)) | 0;
+ hi = (hi + Math.imul(ah7, bh5)) | 0;
+ lo = (lo + Math.imul(al6, bl6)) | 0;
+ mid = (mid + Math.imul(al6, bh6)) | 0;
+ mid = (mid + Math.imul(ah6, bl6)) | 0;
+ hi = (hi + Math.imul(ah6, bh6)) | 0;
+ lo = (lo + Math.imul(al5, bl7)) | 0;
+ mid = (mid + Math.imul(al5, bh7)) | 0;
+ mid = (mid + Math.imul(ah5, bl7)) | 0;
+ hi = (hi + Math.imul(ah5, bh7)) | 0;
+ lo = (lo + Math.imul(al4, bl8)) | 0;
+ mid = (mid + Math.imul(al4, bh8)) | 0;
+ mid = (mid + Math.imul(ah4, bl8)) | 0;
+ hi = (hi + Math.imul(ah4, bh8)) | 0;
+ lo = (lo + Math.imul(al3, bl9)) | 0;
+ mid = (mid + Math.imul(al3, bh9)) | 0;
+ mid = (mid + Math.imul(ah3, bl9)) | 0;
+ hi = (hi + Math.imul(ah3, bh9)) | 0;
+ var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
+ w12 &= 0x3ffffff;
+ /* k = 13 */
+ lo = Math.imul(al9, bl4);
+ mid = Math.imul(al9, bh4);
+ mid = (mid + Math.imul(ah9, bl4)) | 0;
+ hi = Math.imul(ah9, bh4);
+ lo = (lo + Math.imul(al8, bl5)) | 0;
+ mid = (mid + Math.imul(al8, bh5)) | 0;
+ mid = (mid + Math.imul(ah8, bl5)) | 0;
+ hi = (hi + Math.imul(ah8, bh5)) | 0;
+ lo = (lo + Math.imul(al7, bl6)) | 0;
+ mid = (mid + Math.imul(al7, bh6)) | 0;
+ mid = (mid + Math.imul(ah7, bl6)) | 0;
+ hi = (hi + Math.imul(ah7, bh6)) | 0;
+ lo = (lo + Math.imul(al6, bl7)) | 0;
+ mid = (mid + Math.imul(al6, bh7)) | 0;
+ mid = (mid + Math.imul(ah6, bl7)) | 0;
+ hi = (hi + Math.imul(ah6, bh7)) | 0;
+ lo = (lo + Math.imul(al5, bl8)) | 0;
+ mid = (mid + Math.imul(al5, bh8)) | 0;
+ mid = (mid + Math.imul(ah5, bl8)) | 0;
+ hi = (hi + Math.imul(ah5, bh8)) | 0;
+ lo = (lo + Math.imul(al4, bl9)) | 0;
+ mid = (mid + Math.imul(al4, bh9)) | 0;
+ mid = (mid + Math.imul(ah4, bl9)) | 0;
+ hi = (hi + Math.imul(ah4, bh9)) | 0;
+ var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
+ w13 &= 0x3ffffff;
+ /* k = 14 */
+ lo = Math.imul(al9, bl5);
+ mid = Math.imul(al9, bh5);
+ mid = (mid + Math.imul(ah9, bl5)) | 0;
+ hi = Math.imul(ah9, bh5);
+ lo = (lo + Math.imul(al8, bl6)) | 0;
+ mid = (mid + Math.imul(al8, bh6)) | 0;
+ mid = (mid + Math.imul(ah8, bl6)) | 0;
+ hi = (hi + Math.imul(ah8, bh6)) | 0;
+ lo = (lo + Math.imul(al7, bl7)) | 0;
+ mid = (mid + Math.imul(al7, bh7)) | 0;
+ mid = (mid + Math.imul(ah7, bl7)) | 0;
+ hi = (hi + Math.imul(ah7, bh7)) | 0;
+ lo = (lo + Math.imul(al6, bl8)) | 0;
+ mid = (mid + Math.imul(al6, bh8)) | 0;
+ mid = (mid + Math.imul(ah6, bl8)) | 0;
+ hi = (hi + Math.imul(ah6, bh8)) | 0;
+ lo = (lo + Math.imul(al5, bl9)) | 0;
+ mid = (mid + Math.imul(al5, bh9)) | 0;
+ mid = (mid + Math.imul(ah5, bl9)) | 0;
+ hi = (hi + Math.imul(ah5, bh9)) | 0;
+ var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
+ w14 &= 0x3ffffff;
+ /* k = 15 */
+ lo = Math.imul(al9, bl6);
+ mid = Math.imul(al9, bh6);
+ mid = (mid + Math.imul(ah9, bl6)) | 0;
+ hi = Math.imul(ah9, bh6);
+ lo = (lo + Math.imul(al8, bl7)) | 0;
+ mid = (mid + Math.imul(al8, bh7)) | 0;
+ mid = (mid + Math.imul(ah8, bl7)) | 0;
+ hi = (hi + Math.imul(ah8, bh7)) | 0;
+ lo = (lo + Math.imul(al7, bl8)) | 0;
+ mid = (mid + Math.imul(al7, bh8)) | 0;
+ mid = (mid + Math.imul(ah7, bl8)) | 0;
+ hi = (hi + Math.imul(ah7, bh8)) | 0;
+ lo = (lo + Math.imul(al6, bl9)) | 0;
+ mid = (mid + Math.imul(al6, bh9)) | 0;
+ mid = (mid + Math.imul(ah6, bl9)) | 0;
+ hi = (hi + Math.imul(ah6, bh9)) | 0;
+ var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
+ w15 &= 0x3ffffff;
+ /* k = 16 */
+ lo = Math.imul(al9, bl7);
+ mid = Math.imul(al9, bh7);
+ mid = (mid + Math.imul(ah9, bl7)) | 0;
+ hi = Math.imul(ah9, bh7);
+ lo = (lo + Math.imul(al8, bl8)) | 0;
+ mid = (mid + Math.imul(al8, bh8)) | 0;
+ mid = (mid + Math.imul(ah8, bl8)) | 0;
+ hi = (hi + Math.imul(ah8, bh8)) | 0;
+ lo = (lo + Math.imul(al7, bl9)) | 0;
+ mid = (mid + Math.imul(al7, bh9)) | 0;
+ mid = (mid + Math.imul(ah7, bl9)) | 0;
+ hi = (hi + Math.imul(ah7, bh9)) | 0;
+ var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
+ w16 &= 0x3ffffff;
+ /* k = 17 */
+ lo = Math.imul(al9, bl8);
+ mid = Math.imul(al9, bh8);
+ mid = (mid + Math.imul(ah9, bl8)) | 0;
+ hi = Math.imul(ah9, bh8);
+ lo = (lo + Math.imul(al8, bl9)) | 0;
+ mid = (mid + Math.imul(al8, bh9)) | 0;
+ mid = (mid + Math.imul(ah8, bl9)) | 0;
+ hi = (hi + Math.imul(ah8, bh9)) | 0;
+ var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
+ w17 &= 0x3ffffff;
+ /* k = 18 */
+ lo = Math.imul(al9, bl9);
+ mid = Math.imul(al9, bh9);
+ mid = (mid + Math.imul(ah9, bl9)) | 0;
+ hi = Math.imul(ah9, bh9);
+ var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
+ c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
+ w18 &= 0x3ffffff;
+ o[0] = w0;
+ o[1] = w1;
+ o[2] = w2;
+ o[3] = w3;
+ o[4] = w4;
+ o[5] = w5;
+ o[6] = w6;
+ o[7] = w7;
+ o[8] = w8;
+ o[9] = w9;
+ o[10] = w10;
+ o[11] = w11;
+ o[12] = w12;
+ o[13] = w13;
+ o[14] = w14;
+ o[15] = w15;
+ o[16] = w16;
+ o[17] = w17;
+ o[18] = w18;
+ if (c !== 0) {
+ o[19] = c;
+ out.length++;
+ }
+ return out;
+ };
+
+ // Polyfill comb
+ if (!Math.imul) {
+ comb10MulTo = smallMulTo;
+ }
+
+ function bigMulTo (self, num, out) {
+ out.negative = num.negative ^ self.negative;
+ out.length = self.length + num.length;
+
+ var carry = 0;
+ var hncarry = 0;
+ for (var k = 0; k < out.length - 1; k++) {
+ // Sum all words with the same `i + j = k` and accumulate `ncarry`,
+ // note that ncarry could be >= 0x3ffffff
+ var ncarry = hncarry;
+ hncarry = 0;
+ var rword = carry & 0x3ffffff;
+ var maxJ = Math.min(k, num.length - 1);
+ for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
+ var i = k - j;
+ var a = self.words[i] | 0;
+ var b = num.words[j] | 0;
+ var r = a * b;
+
+ var lo = r & 0x3ffffff;
+ ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
+ lo = (lo + rword) | 0;
+ rword = lo & 0x3ffffff;
+ ncarry = (ncarry + (lo >>> 26)) | 0;
+
+ hncarry += ncarry >>> 26;
+ ncarry &= 0x3ffffff;
+ }
+ out.words[k] = rword;
+ carry = ncarry;
+ ncarry = hncarry;
+ }
+ if (carry !== 0) {
+ out.words[k] = carry;
+ } else {
+ out.length--;
+ }
+
+ return out.strip();
+ }
+
+ function jumboMulTo (self, num, out) {
+ var fftm = new FFTM();
+ return fftm.mulp(self, num, out);
+ }
+
+ BN.prototype.mulTo = function mulTo (num, out) {
+ var res;
+ var len = this.length + num.length;
+ if (this.length === 10 && num.length === 10) {
+ res = comb10MulTo(this, num, out);
+ } else if (len < 63) {
+ res = smallMulTo(this, num, out);
+ } else if (len < 1024) {
+ res = bigMulTo(this, num, out);
+ } else {
+ res = jumboMulTo(this, num, out);
+ }
+
+ return res;
+ };
+
+ // Cooley-Tukey algorithm for FFT
+ // slightly revisited to rely on looping instead of recursion
+
+ function FFTM (x, y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ FFTM.prototype.makeRBT = function makeRBT (N) {
+ var t = new Array(N);
+ var l = BN.prototype._countBits(N) - 1;
+ for (var i = 0; i < N; i++) {
+ t[i] = this.revBin(i, l, N);
+ }
+
+ return t;
+ };
+
+ // Returns binary-reversed representation of `x`
+ FFTM.prototype.revBin = function revBin (x, l, N) {
+ if (x === 0 || x === N - 1) return x;
+
+ var rb = 0;
+ for (var i = 0; i < l; i++) {
+ rb |= (x & 1) << (l - i - 1);
+ x >>= 1;
+ }
+
+ return rb;
+ };
+
+ // Performs "tweedling" phase, therefore 'emulating'
+ // behaviour of the recursive algorithm
+ FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
+ for (var i = 0; i < N; i++) {
+ rtws[i] = rws[rbt[i]];
+ itws[i] = iws[rbt[i]];
+ }
+ };
+
+ FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
+ this.permute(rbt, rws, iws, rtws, itws, N);
+
+ for (var s = 1; s < N; s <<= 1) {
+ var l = s << 1;
+
+ var rtwdf = Math.cos(2 * Math.PI / l);
+ var itwdf = Math.sin(2 * Math.PI / l);
+
+ for (var p = 0; p < N; p += l) {
+ var rtwdf_ = rtwdf;
+ var itwdf_ = itwdf;
+
+ for (var j = 0; j < s; j++) {
+ var re = rtws[p + j];
+ var ie = itws[p + j];
+
+ var ro = rtws[p + j + s];
+ var io = itws[p + j + s];
+
+ var rx = rtwdf_ * ro - itwdf_ * io;
+
+ io = rtwdf_ * io + itwdf_ * ro;
+ ro = rx;
+
+ rtws[p + j] = re + ro;
+ itws[p + j] = ie + io;
+
+ rtws[p + j + s] = re - ro;
+ itws[p + j + s] = ie - io;
+
+ /* jshint maxdepth : false */
+ if (j !== l) {
+ rx = rtwdf * rtwdf_ - itwdf * itwdf_;
+
+ itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
+ rtwdf_ = rx;
+ }
+ }
+ }
+ }
+ };
+
+ FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
+ var N = Math.max(m, n) | 1;
+ var odd = N & 1;
+ var i = 0;
+ for (N = N / 2 | 0; N; N = N >>> 1) {
+ i++;
+ }
+
+ return 1 << i + 1 + odd;
+ };
+
+ FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
+ if (N <= 1) return;
+
+ for (var i = 0; i < N / 2; i++) {
+ var t = rws[i];
+
+ rws[i] = rws[N - i - 1];
+ rws[N - i - 1] = t;
+
+ t = iws[i];
+
+ iws[i] = -iws[N - i - 1];
+ iws[N - i - 1] = -t;
+ }
+ };
+
+ FFTM.prototype.normalize13b = function normalize13b (ws, N) {
+ var carry = 0;
+ for (var i = 0; i < N / 2; i++) {
+ var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
+ Math.round(ws[2 * i] / N) +
+ carry;
+
+ ws[i] = w & 0x3ffffff;
+
+ if (w < 0x4000000) {
+ carry = 0;
+ } else {
+ carry = w / 0x4000000 | 0;
+ }
+ }
+
+ return ws;
+ };
+
+ FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
+ var carry = 0;
+ for (var i = 0; i < len; i++) {
+ carry = carry + (ws[i] | 0);
+
+ rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
+ rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
+ }
+
+ // Pad with zeroes
+ for (i = 2 * len; i < N; ++i) {
+ rws[i] = 0;
+ }
+
+ assert(carry === 0);
+ assert((carry & ~0x1fff) === 0);
+ };
+
+ FFTM.prototype.stub = function stub (N) {
+ var ph = new Array(N);
+ for (var i = 0; i < N; i++) {
+ ph[i] = 0;
+ }
+
+ return ph;
+ };
+
+ FFTM.prototype.mulp = function mulp (x, y, out) {
+ var N = 2 * this.guessLen13b(x.length, y.length);
+
+ var rbt = this.makeRBT(N);
+
+ var _ = this.stub(N);
+
+ var rws = new Array(N);
+ var rwst = new Array(N);
+ var iwst = new Array(N);
+
+ var nrws = new Array(N);
+ var nrwst = new Array(N);
+ var niwst = new Array(N);
+
+ var rmws = out.words;
+ rmws.length = N;
+
+ this.convert13b(x.words, x.length, rws, N);
+ this.convert13b(y.words, y.length, nrws, N);
+
+ this.transform(rws, _, rwst, iwst, N, rbt);
+ this.transform(nrws, _, nrwst, niwst, N, rbt);
+
+ for (var i = 0; i < N; i++) {
+ var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
+ iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
+ rwst[i] = rx;
+ }
+
+ this.conjugate(rwst, iwst, N);
+ this.transform(rwst, iwst, rmws, _, N, rbt);
+ this.conjugate(rmws, _, N);
+ this.normalize13b(rmws, N);
+
+ out.negative = x.negative ^ y.negative;
+ out.length = x.length + y.length;
+ return out.strip();
+ };
+
+ // Multiply `this` by `num`
+ BN.prototype.mul = function mul (num) {
+ var out = new BN(null);
+ out.words = new Array(this.length + num.length);
+ return this.mulTo(num, out);
+ };
+
+ // Multiply employing FFT
+ BN.prototype.mulf = function mulf (num) {
+ var out = new BN(null);
+ out.words = new Array(this.length + num.length);
+ return jumboMulTo(this, num, out);
+ };
+
+ // In-place Multiplication
+ BN.prototype.imul = function imul (num) {
+ return this.clone().mulTo(num, this);
+ };
+
+ BN.prototype.imuln = function imuln (num) {
+ assert(typeof num === 'number');
+ assert(num < 0x4000000);
+
+ // Carry
+ var carry = 0;
+ for (var i = 0; i < this.length; i++) {
+ var w = (this.words[i] | 0) * num;
+ var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
+ carry >>= 26;
+ carry += (w / 0x4000000) | 0;
+ // NOTE: lo is 27bit maximum
+ carry += lo >>> 26;
+ this.words[i] = lo & 0x3ffffff;
+ }
+
+ if (carry !== 0) {
+ this.words[i] = carry;
+ this.length++;
+ }
+
+ return this;
+ };
+
+ BN.prototype.muln = function muln (num) {
+ return this.clone().imuln(num);
+ };
+
+ // `this` * `this`
+ BN.prototype.sqr = function sqr () {
+ return this.mul(this);
+ };
+
+ // `this` * `this` in-place
+ BN.prototype.isqr = function isqr () {
+ return this.imul(this.clone());
+ };
+
+ // Math.pow(`this`, `num`)
+ BN.prototype.pow = function pow (num) {
+ var w = toBitArray(num);
+ if (w.length === 0) return new BN(1);
+
+ // Skip leading zeroes
+ var res = this;
+ for (var i = 0; i < w.length; i++, res = res.sqr()) {
+ if (w[i] !== 0) break;
+ }
+
+ if (++i < w.length) {
+ for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
+ if (w[i] === 0) continue;
+
+ res = res.mul(q);
+ }
+ }
+
+ return res;
+ };
+
+ // Shift-left in-place
+ BN.prototype.iushln = function iushln (bits) {
+ assert(typeof bits === 'number' && bits >= 0);
+ var r = bits % 26;
+ var s = (bits - r) / 26;
+ var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
+ var i;
+
+ if (r !== 0) {
+ var carry = 0;
+
+ for (i = 0; i < this.length; i++) {
+ var newCarry = this.words[i] & carryMask;
+ var c = ((this.words[i] | 0) - newCarry) << r;
+ this.words[i] = c | carry;
+ carry = newCarry >>> (26 - r);
+ }
+
+ if (carry) {
+ this.words[i] = carry;
+ this.length++;
+ }
+ }
+
+ if (s !== 0) {
+ for (i = this.length - 1; i >= 0; i--) {
+ this.words[i + s] = this.words[i];
+ }
+
+ for (i = 0; i < s; i++) {
+ this.words[i] = 0;
+ }
+
+ this.length += s;
+ }
+
+ return this.strip();
+ };
+
+ BN.prototype.ishln = function ishln (bits) {
+ // TODO(indutny): implement me
+ assert(this.negative === 0);
+ return this.iushln(bits);
+ };
+
+ // Shift-right in-place
+ // NOTE: `hint` is a lowest bit before trailing zeroes
+ // NOTE: if `extended` is present - it will be filled with destroyed bits
+ BN.prototype.iushrn = function iushrn (bits, hint, extended) {
+ assert(typeof bits === 'number' && bits >= 0);
+ var h;
+ if (hint) {
+ h = (hint - (hint % 26)) / 26;
+ } else {
+ h = 0;
+ }
+
+ var r = bits % 26;
+ var s = Math.min((bits - r) / 26, this.length);
+ var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
+ var maskedWords = extended;
+
+ h -= s;
+ h = Math.max(0, h);
+
+ // Extended mode, copy masked part
+ if (maskedWords) {
+ for (var i = 0; i < s; i++) {
+ maskedWords.words[i] = this.words[i];
+ }
+ maskedWords.length = s;
+ }
+
+ if (s === 0) {
+ // No-op, we should not move anything at all
+ } else if (this.length > s) {
+ this.length -= s;
+ for (i = 0; i < this.length; i++) {
+ this.words[i] = this.words[i + s];
+ }
+ } else {
+ this.words[0] = 0;
+ this.length = 1;
+ }
+
+ var carry = 0;
+ for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
+ var word = this.words[i] | 0;
+ this.words[i] = (carry << (26 - r)) | (word >>> r);
+ carry = word & mask;
+ }
+
+ // Push carried bits as a mask
+ if (maskedWords && carry !== 0) {
+ maskedWords.words[maskedWords.length++] = carry;
+ }
+
+ if (this.length === 0) {
+ this.words[0] = 0;
+ this.length = 1;
+ }
+
+ return this.strip();
+ };
+
+ BN.prototype.ishrn = function ishrn (bits, hint, extended) {
+ // TODO(indutny): implement me
+ assert(this.negative === 0);
+ return this.iushrn(bits, hint, extended);
+ };
+
+ // Shift-left
+ BN.prototype.shln = function shln (bits) {
+ return this.clone().ishln(bits);
+ };
+
+ BN.prototype.ushln = function ushln (bits) {
+ return this.clone().iushln(bits);
+ };
+
+ // Shift-right
+ BN.prototype.shrn = function shrn (bits) {
+ return this.clone().ishrn(bits);
+ };
+
+ BN.prototype.ushrn = function ushrn (bits) {
+ return this.clone().iushrn(bits);
+ };
+
+ // Test if n bit is set
+ BN.prototype.testn = function testn (bit) {
+ assert(typeof bit === 'number' && bit >= 0);
+ var r = bit % 26;
+ var s = (bit - r) / 26;
+ var q = 1 << r;
+
+ // Fast case: bit is much higher than all existing words
+ if (this.length <= s) return false;
+
+ // Check bit and return
+ var w = this.words[s];
+
+ return !!(w & q);
+ };
+
+ // Return only lowers bits of number (in-place)
+ BN.prototype.imaskn = function imaskn (bits) {
+ assert(typeof bits === 'number' && bits >= 0);
+ var r = bits % 26;
+ var s = (bits - r) / 26;
+
+ assert(this.negative === 0, 'imaskn works only with positive numbers');
+
+ if (this.length <= s) {
+ return this;
+ }
+
+ if (r !== 0) {
+ s++;
+ }
+ this.length = Math.min(s, this.length);
+
+ if (r !== 0) {
+ var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
+ this.words[this.length - 1] &= mask;
+ }
+
+ return this.strip();
+ };
+
+ // Return only lowers bits of number
+ BN.prototype.maskn = function maskn (bits) {
+ return this.clone().imaskn(bits);
+ };
+
+ // Add plain number `num` to `this`
+ BN.prototype.iaddn = function iaddn (num) {
+ assert(typeof num === 'number');
+ assert(num < 0x4000000);
+ if (num < 0) return this.isubn(-num);
+
+ // Possible sign change
+ if (this.negative !== 0) {
+ if (this.length === 1 && (this.words[0] | 0) < num) {
+ this.words[0] = num - (this.words[0] | 0);
+ this.negative = 0;
+ return this;
+ }
+
+ this.negative = 0;
+ this.isubn(num);
+ this.negative = 1;
+ return this;
+ }
+
+ // Add without checks
+ return this._iaddn(num);
+ };
+
+ BN.prototype._iaddn = function _iaddn (num) {
+ this.words[0] += num;
+
+ // Carry
+ for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
+ this.words[i] -= 0x4000000;
+ if (i === this.length - 1) {
+ this.words[i + 1] = 1;
+ } else {
+ this.words[i + 1]++;
+ }
+ }
+ this.length = Math.max(this.length, i + 1);
+
+ return this;
+ };
+
+ // Subtract plain number `num` from `this`
+ BN.prototype.isubn = function isubn (num) {
+ assert(typeof num === 'number');
+ assert(num < 0x4000000);
+ if (num < 0) return this.iaddn(-num);
+
+ if (this.negative !== 0) {
+ this.negative = 0;
+ this.iaddn(num);
+ this.negative = 1;
+ return this;
+ }
+
+ this.words[0] -= num;
+
+ if (this.length === 1 && this.words[0] < 0) {
+ this.words[0] = -this.words[0];
+ this.negative = 1;
+ } else {
+ // Carry
+ for (var i = 0; i < this.length && this.words[i] < 0; i++) {
+ this.words[i] += 0x4000000;
+ this.words[i + 1] -= 1;
+ }
+ }
+
+ return this.strip();
+ };
+
+ BN.prototype.addn = function addn (num) {
+ return this.clone().iaddn(num);
+ };
+
+ BN.prototype.subn = function subn (num) {
+ return this.clone().isubn(num);
+ };
+
+ BN.prototype.iabs = function iabs () {
+ this.negative = 0;
+
+ return this;
+ };
+
+ BN.prototype.abs = function abs () {
+ return this.clone().iabs();
+ };
+
+ BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
+ var len = num.length + shift;
+ var i;
+
+ this._expand(len);
+
+ var w;
+ var carry = 0;
+ for (i = 0; i < num.length; i++) {
+ w = (this.words[i + shift] | 0) + carry;
+ var right = (num.words[i] | 0) * mul;
+ w -= right & 0x3ffffff;
+ carry = (w >> 26) - ((right / 0x4000000) | 0);
+ this.words[i + shift] = w & 0x3ffffff;
+ }
+ for (; i < this.length - shift; i++) {
+ w = (this.words[i + shift] | 0) + carry;
+ carry = w >> 26;
+ this.words[i + shift] = w & 0x3ffffff;
+ }
+
+ if (carry === 0) return this.strip();
+
+ // Subtraction overflow
+ assert(carry === -1);
+ carry = 0;
+ for (i = 0; i < this.length; i++) {
+ w = -(this.words[i] | 0) + carry;
+ carry = w >> 26;
+ this.words[i] = w & 0x3ffffff;
+ }
+ this.negative = 1;
+
+ return this.strip();
+ };
+
+ BN.prototype._wordDiv = function _wordDiv (num, mode) {
+ var shift = this.length - num.length;
+
+ var a = this.clone();
+ var b = num;
+
+ // Normalize
+ var bhi = b.words[b.length - 1] | 0;
+ var bhiBits = this._countBits(bhi);
+ shift = 26 - bhiBits;
+ if (shift !== 0) {
+ b = b.ushln(shift);
+ a.iushln(shift);
+ bhi = b.words[b.length - 1] | 0;
+ }
+
+ // Initialize quotient
+ var m = a.length - b.length;
+ var q;
+
+ if (mode !== 'mod') {
+ q = new BN(null);
+ q.length = m + 1;
+ q.words = new Array(q.length);
+ for (var i = 0; i < q.length; i++) {
+ q.words[i] = 0;
+ }
+ }
+
+ var diff = a.clone()._ishlnsubmul(b, 1, m);
+ if (diff.negative === 0) {
+ a = diff;
+ if (q) {
+ q.words[m] = 1;
+ }
+ }
+
+ for (var j = m - 1; j >= 0; j--) {
+ var qj = (a.words[b.length + j] | 0) * 0x4000000 +
+ (a.words[b.length + j - 1] | 0);
+
+ // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
+ // (0x7ffffff)
+ qj = Math.min((qj / bhi) | 0, 0x3ffffff);
+
+ a._ishlnsubmul(b, qj, j);
+ while (a.negative !== 0) {
+ qj--;
+ a.negative = 0;
+ a._ishlnsubmul(b, 1, j);
+ if (!a.isZero()) {
+ a.negative ^= 1;
+ }
+ }
+ if (q) {
+ q.words[j] = qj;
+ }
+ }
+ if (q) {
+ q.strip();
+ }
+ a.strip();
+
+ // Denormalize
+ if (mode !== 'div' && shift !== 0) {
+ a.iushrn(shift);
+ }
+
+ return {
+ div: q || null,
+ mod: a
+ };
+ };
+
+ // NOTE: 1) `mode` can be set to `mod` to request mod only,
+ // to `div` to request div only, or be absent to
+ // request both div & mod
+ // 2) `positive` is true if unsigned mod is requested
+ BN.prototype.divmod = function divmod (num, mode, positive) {
+ assert(!num.isZero());
+
+ if (this.isZero()) {
+ return {
+ div: new BN(0),
+ mod: new BN(0)
+ };
+ }
+
+ var div, mod, res;
+ if (this.negative !== 0 && num.negative === 0) {
+ res = this.neg().divmod(num, mode);
+
+ if (mode !== 'mod') {
+ div = res.div.neg();
+ }
+
+ if (mode !== 'div') {
+ mod = res.mod.neg();
+ if (positive && mod.negative !== 0) {
+ mod.iadd(num);
+ }
+ }
+
+ return {
+ div: div,
+ mod: mod
+ };
+ }
+
+ if (this.negative === 0 && num.negative !== 0) {
+ res = this.divmod(num.neg(), mode);
+
+ if (mode !== 'mod') {
+ div = res.div.neg();
+ }
+
+ return {
+ div: div,
+ mod: res.mod
+ };
+ }
+
+ if ((this.negative & num.negative) !== 0) {
+ res = this.neg().divmod(num.neg(), mode);
+
+ if (mode !== 'div') {
+ mod = res.mod.neg();
+ if (positive && mod.negative !== 0) {
+ mod.isub(num);
+ }
+ }
+
+ return {
+ div: res.div,
+ mod: mod
+ };
+ }
+
+ // Both numbers are positive at this point
+
+ // Strip both numbers to approximate shift value
+ if (num.length > this.length || this.cmp(num) < 0) {
+ return {
+ div: new BN(0),
+ mod: this
+ };
+ }
+
+ // Very short reduction
+ if (num.length === 1) {
+ if (mode === 'div') {
+ return {
+ div: this.divn(num.words[0]),
+ mod: null
+ };
+ }
+
+ if (mode === 'mod') {
+ return {
+ div: null,
+ mod: new BN(this.modn(num.words[0]))
+ };
+ }
+
+ return {
+ div: this.divn(num.words[0]),
+ mod: new BN(this.modn(num.words[0]))
+ };
+ }
+
+ return this._wordDiv(num, mode);
+ };
+
+ // Find `this` / `num`
+ BN.prototype.div = function div (num) {
+ return this.divmod(num, 'div', false).div;
+ };
+
+ // Find `this` % `num`
+ BN.prototype.mod = function mod (num) {
+ return this.divmod(num, 'mod', false).mod;
+ };
+
+ BN.prototype.umod = function umod (num) {
+ return this.divmod(num, 'mod', true).mod;
+ };
+
+ // Find Round(`this` / `num`)
+ BN.prototype.divRound = function divRound (num) {
+ var dm = this.divmod(num);
+
+ // Fast case - exact division
+ if (dm.mod.isZero()) return dm.div;
+
+ var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
+
+ var half = num.ushrn(1);
+ var r2 = num.andln(1);
+ var cmp = mod.cmp(half);
+
+ // Round down
+ if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
+
+ // Round up
+ return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
+ };
+
+ BN.prototype.modn = function modn (num) {
+ assert(num <= 0x3ffffff);
+ var p = (1 << 26) % num;
+
+ var acc = 0;
+ for (var i = this.length - 1; i >= 0; i--) {
+ acc = (p * acc + (this.words[i] | 0)) % num;
+ }
+
+ return acc;
+ };
+
+ // In-place division by number
+ BN.prototype.idivn = function idivn (num) {
+ assert(num <= 0x3ffffff);
+
+ var carry = 0;
+ for (var i = this.length - 1; i >= 0; i--) {
+ var w = (this.words[i] | 0) + carry * 0x4000000;
+ this.words[i] = (w / num) | 0;
+ carry = w % num;
+ }
+
+ return this.strip();
+ };
+
+ BN.prototype.divn = function divn (num) {
+ return this.clone().idivn(num);
+ };
+
+ BN.prototype.egcd = function egcd (p) {
+ assert(p.negative === 0);
+ assert(!p.isZero());
+
+ var x = this;
+ var y = p.clone();
+
+ if (x.negative !== 0) {
+ x = x.umod(p);
+ } else {
+ x = x.clone();
+ }
+
+ // A * x + B * y = x
+ var A = new BN(1);
+ var B = new BN(0);
+
+ // C * x + D * y = y
+ var C = new BN(0);
+ var D = new BN(1);
+
+ var g = 0;
+
+ while (x.isEven() && y.isEven()) {
+ x.iushrn(1);
+ y.iushrn(1);
+ ++g;
+ }
+
+ var yp = y.clone();
+ var xp = x.clone();
+
+ while (!x.isZero()) {
+ for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
+ if (i > 0) {
+ x.iushrn(i);
+ while (i-- > 0) {
+ if (A.isOdd() || B.isOdd()) {
+ A.iadd(yp);
+ B.isub(xp);
+ }
+
+ A.iushrn(1);
+ B.iushrn(1);
+ }
+ }
+
+ for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
+ if (j > 0) {
+ y.iushrn(j);
+ while (j-- > 0) {
+ if (C.isOdd() || D.isOdd()) {
+ C.iadd(yp);
+ D.isub(xp);
+ }
+
+ C.iushrn(1);
+ D.iushrn(1);
+ }
+ }
+
+ if (x.cmp(y) >= 0) {
+ x.isub(y);
+ A.isub(C);
+ B.isub(D);
+ } else {
+ y.isub(x);
+ C.isub(A);
+ D.isub(B);
+ }
+ }
+
+ return {
+ a: C,
+ b: D,
+ gcd: y.iushln(g)
+ };
+ };
+
+ // This is reduced incarnation of the binary EEA
+ // above, designated to invert members of the
+ // _prime_ fields F(p) at a maximal speed
+ BN.prototype._invmp = function _invmp (p) {
+ assert(p.negative === 0);
+ assert(!p.isZero());
+
+ var a = this;
+ var b = p.clone();
+
+ if (a.negative !== 0) {
+ a = a.umod(p);
+ } else {
+ a = a.clone();
+ }
+
+ var x1 = new BN(1);
+ var x2 = new BN(0);
+
+ var delta = b.clone();
+
+ while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
+ for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
+ if (i > 0) {
+ a.iushrn(i);
+ while (i-- > 0) {
+ if (x1.isOdd()) {
+ x1.iadd(delta);
+ }
+
+ x1.iushrn(1);
+ }
+ }
+
+ for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
+ if (j > 0) {
+ b.iushrn(j);
+ while (j-- > 0) {
+ if (x2.isOdd()) {
+ x2.iadd(delta);
+ }
+
+ x2.iushrn(1);
+ }
+ }
+
+ if (a.cmp(b) >= 0) {
+ a.isub(b);
+ x1.isub(x2);
+ } else {
+ b.isub(a);
+ x2.isub(x1);
+ }
+ }
+
+ var res;
+ if (a.cmpn(1) === 0) {
+ res = x1;
+ } else {
+ res = x2;
+ }
+
+ if (res.cmpn(0) < 0) {
+ res.iadd(p);
+ }
+
+ return res;
+ };
+
+ BN.prototype.gcd = function gcd (num) {
+ if (this.isZero()) return num.abs();
+ if (num.isZero()) return this.abs();
+
+ var a = this.clone();
+ var b = num.clone();
+ a.negative = 0;
+ b.negative = 0;
+
+ // Remove common factor of two
+ for (var shift = 0; a.isEven() && b.isEven(); shift++) {
+ a.iushrn(1);
+ b.iushrn(1);
+ }
+
+ do {
+ while (a.isEven()) {
+ a.iushrn(1);
+ }
+ while (b.isEven()) {
+ b.iushrn(1);
+ }
+
+ var r = a.cmp(b);
+ if (r < 0) {
+ // Swap `a` and `b` to make `a` always bigger than `b`
+ var t = a;
+ a = b;
+ b = t;
+ } else if (r === 0 || b.cmpn(1) === 0) {
+ break;
+ }
+
+ a.isub(b);
+ } while (true);
+
+ return b.iushln(shift);
+ };
+
+ // Invert number in the field F(num)
+ BN.prototype.invm = function invm (num) {
+ return this.egcd(num).a.umod(num);
+ };
+
+ BN.prototype.isEven = function isEven () {
+ return (this.words[0] & 1) === 0;
+ };
+
+ BN.prototype.isOdd = function isOdd () {
+ return (this.words[0] & 1) === 1;
+ };
+
+ // And first word and num
+ BN.prototype.andln = function andln (num) {
+ return this.words[0] & num;
+ };
+
+ // Increment at the bit position in-line
+ BN.prototype.bincn = function bincn (bit) {
+ assert(typeof bit === 'number');
+ var r = bit % 26;
+ var s = (bit - r) / 26;
+ var q = 1 << r;
+
+ // Fast case: bit is much higher than all existing words
+ if (this.length <= s) {
+ this._expand(s + 1);
+ this.words[s] |= q;
+ return this;
+ }
+
+ // Add bit and propagate, if needed
+ var carry = q;
+ for (var i = s; carry !== 0 && i < this.length; i++) {
+ var w = this.words[i] | 0;
+ w += carry;
+ carry = w >>> 26;
+ w &= 0x3ffffff;
+ this.words[i] = w;
+ }
+ if (carry !== 0) {
+ this.words[i] = carry;
+ this.length++;
+ }
+ return this;
+ };
+
+ BN.prototype.isZero = function isZero () {
+ return this.length === 1 && this.words[0] === 0;
+ };
+
+ BN.prototype.cmpn = function cmpn (num) {
+ var negative = num < 0;
+
+ if (this.negative !== 0 && !negative) return -1;
+ if (this.negative === 0 && negative) return 1;
+
+ this.strip();
+
+ var res;
+ if (this.length > 1) {
+ res = 1;
+ } else {
+ if (negative) {
+ num = -num;
+ }
+
+ assert(num <= 0x3ffffff, 'Number is too big');
+
+ var w = this.words[0] | 0;
+ res = w === num ? 0 : w < num ? -1 : 1;
+ }
+ if (this.negative !== 0) return -res | 0;
+ return res;
+ };
+
+ // Compare two numbers and return:
+ // 1 - if `this` > `num`
+ // 0 - if `this` == `num`
+ // -1 - if `this` < `num`
+ BN.prototype.cmp = function cmp (num) {
+ if (this.negative !== 0 && num.negative === 0) return -1;
+ if (this.negative === 0 && num.negative !== 0) return 1;
+
+ var res = this.ucmp(num);
+ if (this.negative !== 0) return -res | 0;
+ return res;
+ };
+
+ // Unsigned comparison
+ BN.prototype.ucmp = function ucmp (num) {
+ // At this point both numbers have the same sign
+ if (this.length > num.length) return 1;
+ if (this.length < num.length) return -1;
+
+ var res = 0;
+ for (var i = this.length - 1; i >= 0; i--) {
+ var a = this.words[i] | 0;
+ var b = num.words[i] | 0;
+
+ if (a === b) continue;
+ if (a < b) {
+ res = -1;
+ } else if (a > b) {
+ res = 1;
+ }
+ break;
+ }
+ return res;
+ };
+
+ BN.prototype.gtn = function gtn (num) {
+ return this.cmpn(num) === 1;
+ };
+
+ BN.prototype.gt = function gt (num) {
+ return this.cmp(num) === 1;
+ };
+
+ BN.prototype.gten = function gten (num) {
+ return this.cmpn(num) >= 0;
+ };
+
+ BN.prototype.gte = function gte (num) {
+ return this.cmp(num) >= 0;
+ };
+
+ BN.prototype.ltn = function ltn (num) {
+ return this.cmpn(num) === -1;
+ };
+
+ BN.prototype.lt = function lt (num) {
+ return this.cmp(num) === -1;
+ };
+
+ BN.prototype.lten = function lten (num) {
+ return this.cmpn(num) <= 0;
+ };
+
+ BN.prototype.lte = function lte (num) {
+ return this.cmp(num) <= 0;
+ };
+
+ BN.prototype.eqn = function eqn (num) {
+ return this.cmpn(num) === 0;
+ };
+
+ BN.prototype.eq = function eq (num) {
+ return this.cmp(num) === 0;
+ };
+
+ //
+ // A reduce context, could be using montgomery or something better, depending
+ // on the `m` itself.
+ //
+ BN.red = function red (num) {
+ return new Red(num);
+ };
+
+ BN.prototype.toRed = function toRed (ctx) {
+ assert(!this.red, 'Already a number in reduction context');
+ assert(this.negative === 0, 'red works only with positives');
+ return ctx.convertTo(this)._forceRed(ctx);
+ };
+
+ BN.prototype.fromRed = function fromRed () {
+ assert(this.red, 'fromRed works only with numbers in reduction context');
+ return this.red.convertFrom(this);
+ };
+
+ BN.prototype._forceRed = function _forceRed (ctx) {
+ this.red = ctx;
+ return this;
+ };
+
+ BN.prototype.forceRed = function forceRed (ctx) {
+ assert(!this.red, 'Already a number in reduction context');
+ return this._forceRed(ctx);
+ };
+
+ BN.prototype.redAdd = function redAdd (num) {
+ assert(this.red, 'redAdd works only with red numbers');
+ return this.red.add(this, num);
+ };
+
+ BN.prototype.redIAdd = function redIAdd (num) {
+ assert(this.red, 'redIAdd works only with red numbers');
+ return this.red.iadd(this, num);
+ };
+
+ BN.prototype.redSub = function redSub (num) {
+ assert(this.red, 'redSub works only with red numbers');
+ return this.red.sub(this, num);
+ };
+
+ BN.prototype.redISub = function redISub (num) {
+ assert(this.red, 'redISub works only with red numbers');
+ return this.red.isub(this, num);
+ };
+
+ BN.prototype.redShl = function redShl (num) {
+ assert(this.red, 'redShl works only with red numbers');
+ return this.red.shl(this, num);
+ };
+
+ BN.prototype.redMul = function redMul (num) {
+ assert(this.red, 'redMul works only with red numbers');
+ this.red._verify2(this, num);
+ return this.red.mul(this, num);
+ };
+
+ BN.prototype.redIMul = function redIMul (num) {
+ assert(this.red, 'redMul works only with red numbers');
+ this.red._verify2(this, num);
+ return this.red.imul(this, num);
+ };
+
+ BN.prototype.redSqr = function redSqr () {
+ assert(this.red, 'redSqr works only with red numbers');
+ this.red._verify1(this);
+ return this.red.sqr(this);
+ };
+
+ BN.prototype.redISqr = function redISqr () {
+ assert(this.red, 'redISqr works only with red numbers');
+ this.red._verify1(this);
+ return this.red.isqr(this);
+ };
+
+ // Square root over p
+ BN.prototype.redSqrt = function redSqrt () {
+ assert(this.red, 'redSqrt works only with red numbers');
+ this.red._verify1(this);
+ return this.red.sqrt(this);
+ };
+
+ BN.prototype.redInvm = function redInvm () {
+ assert(this.red, 'redInvm works only with red numbers');
+ this.red._verify1(this);
+ return this.red.invm(this);
+ };
+
+ // Return negative clone of `this` % `red modulo`
+ BN.prototype.redNeg = function redNeg () {
+ assert(this.red, 'redNeg works only with red numbers');
+ this.red._verify1(this);
+ return this.red.neg(this);
+ };
+
+ BN.prototype.redPow = function redPow (num) {
+ assert(this.red && !num.red, 'redPow(normalNum)');
+ this.red._verify1(this);
+ return this.red.pow(this, num);
+ };
+
+ // Prime numbers with efficient reduction
+ var primes = {
+ k256: null,
+ p224: null,
+ p192: null,
+ p25519: null
+ };
+
+ // Pseudo-Mersenne prime
+ function MPrime (name, p) {
+ // P = 2 ^ N - K
+ this.name = name;
+ this.p = new BN(p, 16);
+ this.n = this.p.bitLength();
+ this.k = new BN(1).iushln(this.n).isub(this.p);
+
+ this.tmp = this._tmp();
+ }
+
+ MPrime.prototype._tmp = function _tmp () {
+ var tmp = new BN(null);
+ tmp.words = new Array(Math.ceil(this.n / 13));
+ return tmp;
+ };
+
+ MPrime.prototype.ireduce = function ireduce (num) {
+ // Assumes that `num` is less than `P^2`
+ // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
+ var r = num;
+ var rlen;
+
+ do {
+ this.split(r, this.tmp);
+ r = this.imulK(r);
+ r = r.iadd(this.tmp);
+ rlen = r.bitLength();
+ } while (rlen > this.n);
+
+ var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
+ if (cmp === 0) {
+ r.words[0] = 0;
+ r.length = 1;
+ } else if (cmp > 0) {
+ r.isub(this.p);
+ } else {
+ r.strip();
+ }
+
+ return r;
+ };
+
+ MPrime.prototype.split = function split (input, out) {
+ input.iushrn(this.n, 0, out);
+ };
+
+ MPrime.prototype.imulK = function imulK (num) {
+ return num.imul(this.k);
+ };
+
+ function K256 () {
+ MPrime.call(
+ this,
+ 'k256',
+ 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
+ }
+ inherits(K256, MPrime);
+
+ K256.prototype.split = function split (input, output) {
+ // 256 = 9 * 26 + 22
+ var mask = 0x3fffff;
+
+ var outLen = Math.min(input.length, 9);
+ for (var i = 0; i < outLen; i++) {
+ output.words[i] = input.words[i];
+ }
+ output.length = outLen;
+
+ if (input.length <= 9) {
+ input.words[0] = 0;
+ input.length = 1;
+ return;
+ }
+
+ // Shift by 9 limbs
+ var prev = input.words[9];
+ output.words[output.length++] = prev & mask;
+
+ for (i = 10; i < input.length; i++) {
+ var next = input.words[i] | 0;
+ input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
+ prev = next;
+ }
+ prev >>>= 22;
+ input.words[i - 10] = prev;
+ if (prev === 0 && input.length > 10) {
+ input.length -= 10;
+ } else {
+ input.length -= 9;
+ }
+ };
+
+ K256.prototype.imulK = function imulK (num) {
+ // K = 0x1000003d1 = [ 0x40, 0x3d1 ]
+ num.words[num.length] = 0;
+ num.words[num.length + 1] = 0;
+ num.length += 2;
+
+ // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
+ var lo = 0;
+ for (var i = 0; i < num.length; i++) {
+ var w = num.words[i] | 0;
+ lo += w * 0x3d1;
+ num.words[i] = lo & 0x3ffffff;
+ lo = w * 0x40 + ((lo / 0x4000000) | 0);
+ }
+
+ // Fast length reduction
+ if (num.words[num.length - 1] === 0) {
+ num.length--;
+ if (num.words[num.length - 1] === 0) {
+ num.length--;
+ }
+ }
+ return num;
+ };
+
+ function P224 () {
+ MPrime.call(
+ this,
+ 'p224',
+ 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
+ }
+ inherits(P224, MPrime);
+
+ function P192 () {
+ MPrime.call(
+ this,
+ 'p192',
+ 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
+ }
+ inherits(P192, MPrime);
+
+ function P25519 () {
+ // 2 ^ 255 - 19
+ MPrime.call(
+ this,
+ '25519',
+ '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
+ }
+ inherits(P25519, MPrime);
+
+ P25519.prototype.imulK = function imulK (num) {
+ // K = 0x13
+ var carry = 0;
+ for (var i = 0; i < num.length; i++) {
+ var hi = (num.words[i] | 0) * 0x13 + carry;
+ var lo = hi & 0x3ffffff;
+ hi >>>= 26;
+
+ num.words[i] = lo;
+ carry = hi;
+ }
+ if (carry !== 0) {
+ num.words[num.length++] = carry;
+ }
+ return num;
+ };
+
+ // Exported mostly for testing purposes, use plain name instead
+ BN._prime = function prime (name) {
+ // Cached version of prime
+ if (primes[name]) return primes[name];
+
+ var prime;
+ if (name === 'k256') {
+ prime = new K256();
+ } else if (name === 'p224') {
+ prime = new P224();
+ } else if (name === 'p192') {
+ prime = new P192();
+ } else if (name === 'p25519') {
+ prime = new P25519();
+ } else {
+ throw new Error('Unknown prime ' + name);
+ }
+ primes[name] = prime;
+
+ return prime;
+ };
+
+ //
+ // Base reduction engine
+ //
+ function Red (m) {
+ if (typeof m === 'string') {
+ var prime = BN._prime(m);
+ this.m = prime.p;
+ this.prime = prime;
+ } else {
+ assert(m.gtn(1), 'modulus must be greater than 1');
+ this.m = m;
+ this.prime = null;
+ }
+ }
+
+ Red.prototype._verify1 = function _verify1 (a) {
+ assert(a.negative === 0, 'red works only with positives');
+ assert(a.red, 'red works only with red numbers');
+ };
+
+ Red.prototype._verify2 = function _verify2 (a, b) {
+ assert((a.negative | b.negative) === 0, 'red works only with positives');
+ assert(a.red && a.red === b.red,
+ 'red works only with red numbers');
+ };
+
+ Red.prototype.imod = function imod (a) {
+ if (this.prime) return this.prime.ireduce(a)._forceRed(this);
+ return a.umod(this.m)._forceRed(this);
+ };
+
+ Red.prototype.neg = function neg (a) {
+ if (a.isZero()) {
+ return a.clone();
+ }
+
+ return this.m.sub(a)._forceRed(this);
+ };
+
+ Red.prototype.add = function add (a, b) {
+ this._verify2(a, b);
+
+ var res = a.add(b);
+ if (res.cmp(this.m) >= 0) {
+ res.isub(this.m);
+ }
+ return res._forceRed(this);
+ };
+
+ Red.prototype.iadd = function iadd (a, b) {
+ this._verify2(a, b);
+
+ var res = a.iadd(b);
+ if (res.cmp(this.m) >= 0) {
+ res.isub(this.m);
+ }
+ return res;
+ };
+
+ Red.prototype.sub = function sub (a, b) {
+ this._verify2(a, b);
+
+ var res = a.sub(b);
+ if (res.cmpn(0) < 0) {
+ res.iadd(this.m);
+ }
+ return res._forceRed(this);
+ };
+
+ Red.prototype.isub = function isub (a, b) {
+ this._verify2(a, b);
+
+ var res = a.isub(b);
+ if (res.cmpn(0) < 0) {
+ res.iadd(this.m);
+ }
+ return res;
+ };
+
+ Red.prototype.shl = function shl (a, num) {
+ this._verify1(a);
+ return this.imod(a.ushln(num));
+ };
+
+ Red.prototype.imul = function imul (a, b) {
+ this._verify2(a, b);
+ return this.imod(a.imul(b));
+ };
+
+ Red.prototype.mul = function mul (a, b) {
+ this._verify2(a, b);
+ return this.imod(a.mul(b));
+ };
+
+ Red.prototype.isqr = function isqr (a) {
+ return this.imul(a, a.clone());
+ };
+
+ Red.prototype.sqr = function sqr (a) {
+ return this.mul(a, a);
+ };
+
+ Red.prototype.sqrt = function sqrt (a) {
+ if (a.isZero()) return a.clone();
+
+ var mod3 = this.m.andln(3);
+ assert(mod3 % 2 === 1);
+
+ // Fast case
+ if (mod3 === 3) {
+ var pow = this.m.add(new BN(1)).iushrn(2);
+ return this.pow(a, pow);
+ }
+
+ // Tonelli-Shanks algorithm (Totally unoptimized and slow)
+ //
+ // Find Q and S, that Q * 2 ^ S = (P - 1)
+ var q = this.m.subn(1);
+ var s = 0;
+ while (!q.isZero() && q.andln(1) === 0) {
+ s++;
+ q.iushrn(1);
+ }
+ assert(!q.isZero());
+
+ var one = new BN(1).toRed(this);
+ var nOne = one.redNeg();
+
+ // Find quadratic non-residue
+ // NOTE: Max is such because of generalized Riemann hypothesis.
+ var lpow = this.m.subn(1).iushrn(1);
+ var z = this.m.bitLength();
+ z = new BN(2 * z * z).toRed(this);
+
+ while (this.pow(z, lpow).cmp(nOne) !== 0) {
+ z.redIAdd(nOne);
+ }
+
+ var c = this.pow(z, q);
+ var r = this.pow(a, q.addn(1).iushrn(1));
+ var t = this.pow(a, q);
+ var m = s;
+ while (t.cmp(one) !== 0) {
+ var tmp = t;
+ for (var i = 0; tmp.cmp(one) !== 0; i++) {
+ tmp = tmp.redSqr();
+ }
+ assert(i < m);
+ var b = this.pow(c, new BN(1).iushln(m - i - 1));
+
+ r = r.redMul(b);
+ c = b.redSqr();
+ t = t.redMul(c);
+ m = i;
+ }
+
+ return r;
+ };
+
+ Red.prototype.invm = function invm (a) {
+ var inv = a._invmp(this.m);
+ if (inv.negative !== 0) {
+ inv.negative = 0;
+ return this.imod(inv).redNeg();
+ } else {
+ return this.imod(inv);
+ }
+ };
+
+ Red.prototype.pow = function pow (a, num) {
+ if (num.isZero()) return new BN(1);
+ if (num.cmpn(1) === 0) return a.clone();
+
+ var windowSize = 4;
+ var wnd = new Array(1 << windowSize);
+ wnd[0] = new BN(1).toRed(this);
+ wnd[1] = a;
+ for (var i = 2; i < wnd.length; i++) {
+ wnd[i] = this.mul(wnd[i - 1], a);
+ }
+
+ var res = wnd[0];
+ var current = 0;
+ var currentLen = 0;
+ var start = num.bitLength() % 26;
+ if (start === 0) {
+ start = 26;
+ }
+
+ for (i = num.length - 1; i >= 0; i--) {
+ var word = num.words[i];
+ for (var j = start - 1; j >= 0; j--) {
+ var bit = (word >> j) & 1;
+ if (res !== wnd[0]) {
+ res = this.sqr(res);
+ }
+
+ if (bit === 0 && current === 0) {
+ currentLen = 0;
+ continue;
+ }
+
+ current <<= 1;
+ current |= bit;
+ currentLen++;
+ if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
+
+ res = this.mul(res, wnd[current]);
+ currentLen = 0;
+ current = 0;
+ }
+ start = 26;
+ }
+
+ return res;
+ };
+
+ Red.prototype.convertTo = function convertTo (num) {
+ var r = num.umod(this.m);
+
+ return r === num ? r.clone() : r;
+ };
+
+ Red.prototype.convertFrom = function convertFrom (num) {
+ var res = num.clone();
+ res.red = null;
+ return res;
+ };
+
+ //
+ // Montgomery method engine
+ //
+
+ BN.mont = function mont (num) {
+ return new Mont(num);
+ };
+
+ function Mont (m) {
+ Red.call(this, m);
+
+ this.shift = this.m.bitLength();
+ if (this.shift % 26 !== 0) {
+ this.shift += 26 - (this.shift % 26);
+ }
+
+ this.r = new BN(1).iushln(this.shift);
+ this.r2 = this.imod(this.r.sqr());
+ this.rinv = this.r._invmp(this.m);
+
+ this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
+ this.minv = this.minv.umod(this.r);
+ this.minv = this.r.sub(this.minv);
+ }
+ inherits(Mont, Red);
+
+ Mont.prototype.convertTo = function convertTo (num) {
+ return this.imod(num.ushln(this.shift));
+ };
+
+ Mont.prototype.convertFrom = function convertFrom (num) {
+ var r = this.imod(num.mul(this.rinv));
+ r.red = null;
+ return r;
+ };
+
+ Mont.prototype.imul = function imul (a, b) {
+ if (a.isZero() || b.isZero()) {
+ a.words[0] = 0;
+ a.length = 1;
+ return a;
+ }
+
+ var t = a.imul(b);
+ var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
+ var u = t.isub(c).iushrn(this.shift);
+ var res = u;
+
+ if (u.cmp(this.m) >= 0) {
+ res = u.isub(this.m);
+ } else if (u.cmpn(0) < 0) {
+ res = u.iadd(this.m);
+ }
+
+ return res._forceRed(this);
+ };
+
+ Mont.prototype.mul = function mul (a, b) {
+ if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
+
+ var t = a.mul(b);
+ var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
+ var u = t.isub(c).iushrn(this.shift);
+ var res = u;
+ if (u.cmp(this.m) >= 0) {
+ res = u.isub(this.m);
+ } else if (u.cmpn(0) < 0) {
+ res = u.iadd(this.m);
+ }
+
+ return res._forceRed(this);
+ };
+
+ Mont.prototype.invm = function invm (a) {
+ // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
+ var res = this.imod(a._invmp(this.m).mul(this.r2));
+ return res._forceRed(this);
+ };
+})(typeof module === 'undefined' || module, this);
diff --git a/node_modules/bn.js/package.json b/node_modules/bn.js/package.json
new file mode 100644
index 000000000..88352136e
--- /dev/null
+++ b/node_modules/bn.js/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "bn.js",
+ "version": "4.11.6",
+ "description": "Big number implementation in pure javascript",
+ "main": "lib/bn.js",
+ "scripts": {
+ "lint": "semistandard",
+ "unit": "mocha --reporter=spec test/*-test.js",
+ "test": "npm run lint && npm run unit"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:indutny/bn.js"
+ },
+ "keywords": [
+ "BN",
+ "BigNum",
+ "Big number",
+ "Modulo",
+ "Montgomery"
+ ],
+ "author": "Fedor Indutny <fedor@indutny.com>",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/indutny/bn.js/issues"
+ },
+ "homepage": "https://github.com/indutny/bn.js",
+ "devDependencies": {
+ "istanbul": "^0.3.5",
+ "mocha": "^2.1.0",
+ "semistandard": "^7.0.4"
+ }
+}
diff --git a/node_modules/bn.js/test/arithmetic-test.js b/node_modules/bn.js/test/arithmetic-test.js
new file mode 100644
index 000000000..c3a0d7d5d
--- /dev/null
+++ b/node_modules/bn.js/test/arithmetic-test.js
@@ -0,0 +1,635 @@
+/* global describe, it */
+
+var assert = require('assert');
+var BN = require('../').BN;
+var fixtures = require('./fixtures');
+
+describe('BN.js/Arithmetic', function () {
+ describe('.add()', function () {
+ it('should add numbers', function () {
+ assert.equal(new BN(14).add(new BN(26)).toString(16), '28');
+ var k = new BN(0x1234);
+ var r = k;
+
+ for (var i = 0; i < 257; i++) {
+ r = r.add(k);
+ }
+
+ assert.equal(r.toString(16), '125868');
+ });
+
+ it('should handle carry properly (in-place)', function () {
+ var k = new BN('abcdefabcdefabcdef', 16);
+ var r = new BN('deadbeef', 16);
+
+ for (var i = 0; i < 257; i++) {
+ r.iadd(k);
+ }
+
+ assert.equal(r.toString(16), 'ac79bd9b79be7a277bde');
+ });
+
+ it('should properly do positive + negative', function () {
+ var a = new BN('abcd', 16);
+ var b = new BN('-abce', 16);
+
+ assert.equal(a.iadd(b).toString(16), '-1');
+
+ a = new BN('abcd', 16);
+ b = new BN('-abce', 16);
+
+ assert.equal(a.add(b).toString(16), '-1');
+ assert.equal(b.add(a).toString(16), '-1');
+ });
+ });
+
+ describe('.iaddn()', function () {
+ it('should allow a sign change', function () {
+ var a = new BN(-100);
+ assert.equal(a.negative, 1);
+
+ a.iaddn(200);
+
+ assert.equal(a.negative, 0);
+ assert.equal(a.toString(), '100');
+ });
+
+ it('should add negative number', function () {
+ var a = new BN(-100);
+ assert.equal(a.negative, 1);
+
+ a.iaddn(-200);
+
+ assert.equal(a.toString(), '-300');
+ });
+
+ it('should allow neg + pos with big number', function () {
+ var a = new BN('-1000000000', 10);
+ assert.equal(a.negative, 1);
+
+ a.iaddn(200);
+
+ assert.equal(a.toString(), '-999999800');
+ });
+
+ it('should carry limb', function () {
+ var a = new BN('3ffffff', 16);
+
+ assert.equal(a.iaddn(1).toString(16), '4000000');
+ });
+
+ it('should throw error with num eq 0x4000000', function () {
+ assert.throws(function () {
+ new BN(0).iaddn(0x4000000);
+ }, /^Error: Assertion failed$/);
+ });
+ });
+
+ describe('.sub()', function () {
+ it('should subtract small numbers', function () {
+ assert.equal(new BN(26).sub(new BN(14)).toString(16), 'c');
+ assert.equal(new BN(14).sub(new BN(26)).toString(16), '-c');
+ assert.equal(new BN(26).sub(new BN(26)).toString(16), '0');
+ assert.equal(new BN(-26).sub(new BN(26)).toString(16), '-34');
+ });
+
+ var a = new BN(
+ '31ff3c61db2db84b9823d320907a573f6ad37c437abe458b1802cda041d6384' +
+ 'a7d8daef41395491e2',
+ 16);
+ var b = new BN(
+ '6f0e4d9f1d6071c183677f601af9305721c91d31b0bbbae8fb790000',
+ 16);
+ var r = new BN(
+ '31ff3c61db2db84b9823d3208989726578fd75276287cd9516533a9acfb9a67' +
+ '76281f34583ddb91e2',
+ 16);
+
+ it('should subtract big numbers', function () {
+ assert.equal(a.sub(b).cmp(r), 0);
+ });
+
+ it('should subtract numbers in place', function () {
+ assert.equal(b.clone().isub(a).neg().cmp(r), 0);
+ });
+
+ it('should subtract with carry', function () {
+ // Carry and copy
+ var a = new BN('12345', 16);
+ var b = new BN('1000000000000', 16);
+ assert.equal(a.isub(b).toString(16), '-fffffffedcbb');
+
+ a = new BN('12345', 16);
+ b = new BN('1000000000000', 16);
+ assert.equal(b.isub(a).toString(16), 'fffffffedcbb');
+ });
+ });
+
+ describe('.isubn()', function () {
+ it('should subtract negative number', function () {
+ var r = new BN(
+ '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b', 16);
+ assert.equal(r.isubn(-1).toString(16),
+ '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681c');
+ });
+
+ it('should work for positive numbers', function () {
+ var a = new BN(-100);
+ assert.equal(a.negative, 1);
+
+ a.isubn(200);
+ assert.equal(a.negative, 1);
+ assert.equal(a.toString(), '-300');
+ });
+
+ it('should not allow a sign change', function () {
+ var a = new BN(-100);
+ assert.equal(a.negative, 1);
+
+ a.isubn(-200);
+ assert.equal(a.negative, 0);
+ assert.equal(a.toString(), '100');
+ });
+
+ it('should change sign on small numbers at 0', function () {
+ var a = new BN(0).subn(2);
+ assert.equal(a.toString(), '-2');
+ });
+
+ it('should change sign on small numbers at 1', function () {
+ var a = new BN(1).subn(2);
+ assert.equal(a.toString(), '-1');
+ });
+
+ it('should throw error with num eq 0x4000000', function () {
+ assert.throws(function () {
+ new BN(0).isubn(0x4000000);
+ }, /^Error: Assertion failed$/);
+ });
+ });
+
+ function testMethod (name, mul) {
+ describe(name, function () {
+ it('should multiply numbers of different signs', function () {
+ var offsets = [
+ 1, // smallMulTo
+ 250, // comb10MulTo
+ 1000, // bigMulTo
+ 15000 // jumboMulTo
+ ];
+
+ for (var i = 0; i < offsets.length; ++i) {
+ var x = new BN(1).ishln(offsets[i]);
+
+ assert.equal(mul(x, x).isNeg(), false);
+ assert.equal(mul(x, x.neg()).isNeg(), true);
+ assert.equal(mul(x.neg(), x).isNeg(), true);
+ assert.equal(mul(x.neg(), x.neg()).isNeg(), false);
+ }
+ });
+
+ it('should multiply with carry', function () {
+ var n = new BN(0x1001);
+ var r = n;
+
+ for (var i = 0; i < 4; i++) {
+ r = mul(r, n);
+ }
+
+ assert.equal(r.toString(16), '100500a00a005001');
+ });
+
+ it('should correctly multiply big numbers', function () {
+ var n = new BN(
+ '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
+ 16
+ );
+ assert.equal(
+ mul(n, n).toString(16),
+ '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9' +
+ 'b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9' +
+ '978a8bd8acaa40');
+ assert.equal(
+ mul(mul(n, n), n).toString(16),
+ '1b888e01a06e974017a28a5b4da436169761c9730b7aeedf75fc60f687b' +
+ '46e0cf2cb11667f795d5569482640fe5f628939467a01a612b02350' +
+ '0d0161e9730279a7561043af6197798e41b7432458463e64fa81158' +
+ '907322dc330562697d0d600');
+ });
+
+ it('should multiply neg number on 0', function () {
+ assert.equal(
+ mul(new BN('-100000000000'), new BN('3').div(new BN('4')))
+ .toString(16),
+ '0'
+ );
+ });
+
+ it('should regress mul big numbers', function () {
+ var q = fixtures.dhGroups.p17.q;
+ var qs = fixtures.dhGroups.p17.qs;
+
+ q = new BN(q, 16);
+ assert.equal(mul(q, q).toString(16), qs);
+ });
+ });
+ }
+
+ testMethod('.mul()', function (x, y) {
+ return BN.prototype.mul.apply(x, [ y ]);
+ });
+
+ testMethod('.mulf()', function (x, y) {
+ return BN.prototype.mulf.apply(x, [ y ]);
+ });
+
+ describe('.imul()', function () {
+ it('should multiply numbers in-place', function () {
+ var a = new BN('abcdef01234567890abcd', 16);
+ var b = new BN('deadbeefa551edebabba8', 16);
+ var c = a.mul(b);
+
+ assert.equal(a.imul(b).toString(16), c.toString(16));
+
+ a = new BN('abcdef01234567890abcd214a25123f512361e6d236', 16);
+ b = new BN('deadbeefa551edebabba8121234fd21bac0341324dd', 16);
+ c = a.mul(b);
+
+ assert.equal(a.imul(b).toString(16), c.toString(16));
+ });
+
+ it('should multiply by 0', function () {
+ var a = new BN('abcdef01234567890abcd', 16);
+ var b = new BN('0', 16);
+ var c = a.mul(b);
+
+ assert.equal(a.imul(b).toString(16), c.toString(16));
+ });
+
+ it('should regress mul big numbers in-place', function () {
+ var q = fixtures.dhGroups.p17.q;
+ var qs = fixtures.dhGroups.p17.qs;
+
+ q = new BN(q, 16);
+
+ assert.equal(q.isqr().toString(16), qs);
+ });
+ });
+
+ describe('.muln()', function () {
+ it('should multiply number by small number', function () {
+ var a = new BN('abcdef01234567890abcd', 16);
+ var b = new BN('dead', 16);
+ var c = a.mul(b);
+
+ assert.equal(a.muln(0xdead).toString(16), c.toString(16));
+ });
+
+ it('should throw error with num eq 0x4000000', function () {
+ assert.throws(function () {
+ new BN(0).imuln(0x4000000);
+ }, /^Error: Assertion failed$/);
+ });
+ });
+
+ describe('.pow()', function () {
+ it('should raise number to the power', function () {
+ var a = new BN('ab', 16);
+ var b = new BN('13', 10);
+ var c = a.pow(b);
+
+ assert.equal(c.toString(16), '15963da06977df51909c9ba5b');
+ });
+ });
+
+ describe('.div()', function () {
+ it('should divide small numbers (<=26 bits)', function () {
+ assert.equal(new BN('256').div(new BN(10)).toString(10),
+ '25');
+ assert.equal(new BN('-256').div(new BN(10)).toString(10),
+ '-25');
+ assert.equal(new BN('256').div(new BN(-10)).toString(10),
+ '-25');
+ assert.equal(new BN('-256').div(new BN(-10)).toString(10),
+ '25');
+
+ assert.equal(new BN('10').div(new BN(256)).toString(10),
+ '0');
+ assert.equal(new BN('-10').div(new BN(256)).toString(10),
+ '0');
+ assert.equal(new BN('10').div(new BN(-256)).toString(10),
+ '0');
+ assert.equal(new BN('-10').div(new BN(-256)).toString(10),
+ '0');
+ });
+
+ it('should divide large numbers (>53 bits)', function () {
+ assert.equal(new BN('1222222225255589').div(new BN('611111124969028'))
+ .toString(10), '1');
+ assert.equal(new BN('-1222222225255589').div(new BN('611111124969028'))
+ .toString(10), '-1');
+ assert.equal(new BN('1222222225255589').div(new BN('-611111124969028'))
+ .toString(10), '-1');
+ assert.equal(new BN('-1222222225255589').div(new BN('-611111124969028'))
+ .toString(10), '1');
+
+ assert.equal(new BN('611111124969028').div(new BN('1222222225255589'))
+ .toString(10), '0');
+ assert.equal(new BN('-611111124969028').div(new BN('1222222225255589'))
+ .toString(10), '0');
+ assert.equal(new BN('611111124969028').div(new BN('-1222222225255589'))
+ .toString(10), '0');
+ assert.equal(new BN('-611111124969028').div(new BN('-1222222225255589'))
+ .toString(10), '0');
+ });
+
+ it('should divide numbers', function () {
+ assert.equal(new BN('69527932928').div(new BN('16974594')).toString(16),
+ 'fff');
+ assert.equal(new BN('-69527932928').div(new BN('16974594')).toString(16),
+ '-fff');
+
+ var b = new BN(
+ '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9' +
+ 'b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9' +
+ '978a8bd8acaa40',
+ 16);
+ var n = new BN(
+ '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
+ 16
+ );
+ assert.equal(b.div(n).toString(16), n.toString(16));
+
+ assert.equal(new BN('1').div(new BN('-5')).toString(10), '0');
+ });
+
+ it('should not fail on regression after moving to _wordDiv', function () {
+ // Regression after moving to word div
+ var p = new BN(
+ 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f',
+ 16);
+ var a = new BN(
+ '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
+ 16);
+ var as = a.sqr();
+ assert.equal(
+ as.div(p).toString(16),
+ '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729e58090b9');
+
+ p = new BN(
+ 'ffffffff00000001000000000000000000000000ffffffffffffffffffffffff',
+ 16);
+ a = new BN(
+ 'fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffff' +
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
+ 16);
+ assert.equal(
+ a.div(p).toString(16),
+ 'ffffffff00000002000000000000000000000001000000000000000000000001');
+ });
+ });
+
+ describe('.idivn()', function () {
+ it('should divide numbers in-place', function () {
+ assert.equal(new BN('10', 16).idivn(3).toString(16), '5');
+ assert.equal(new BN('12', 16).idivn(3).toString(16), '6');
+ assert.equal(new BN('10000000000000000').idivn(3).toString(10),
+ '3333333333333333');
+ assert.equal(
+ new BN('100000000000000000000000000000').idivn(3).toString(10),
+ '33333333333333333333333333333');
+
+ var t = new BN(3);
+ assert.equal(
+ new BN('12345678901234567890123456', 16).idivn(3).toString(16),
+ new BN('12345678901234567890123456', 16).div(t).toString(16));
+ });
+ });
+
+ describe('.divRound()', function () {
+ it('should divide numbers with rounding', function () {
+ assert.equal(new BN(9).divRound(new BN(20)).toString(10),
+ '0');
+ assert.equal(new BN(10).divRound(new BN(20)).toString(10),
+ '1');
+ assert.equal(new BN(150).divRound(new BN(20)).toString(10),
+ '8');
+ assert.equal(new BN(149).divRound(new BN(20)).toString(10),
+ '7');
+ assert.equal(new BN(149).divRound(new BN(17)).toString(10),
+ '9');
+ assert.equal(new BN(144).divRound(new BN(17)).toString(10),
+ '8');
+ assert.equal(new BN(-144).divRound(new BN(17)).toString(10),
+ '-8');
+ });
+
+ it('should return 1 on exact division', function () {
+ assert.equal(new BN(144).divRound(new BN(144)).toString(10), '1');
+ });
+ });
+
+ describe('.mod()', function () {
+ it('should modulo small numbers (<=26 bits)', function () {
+ assert.equal(new BN('256').mod(new BN(10)).toString(10),
+ '6');
+ assert.equal(new BN('-256').mod(new BN(10)).toString(10),
+ '-6');
+ assert.equal(new BN('256').mod(new BN(-10)).toString(10),
+ '6');
+ assert.equal(new BN('-256').mod(new BN(-10)).toString(10),
+ '-6');
+
+ assert.equal(new BN('10').mod(new BN(256)).toString(10),
+ '10');
+ assert.equal(new BN('-10').mod(new BN(256)).toString(10),
+ '-10');
+ assert.equal(new BN('10').mod(new BN(-256)).toString(10),
+ '10');
+ assert.equal(new BN('-10').mod(new BN(-256)).toString(10),
+ '-10');
+ });
+
+ it('should modulo large numbers (>53 bits)', function () {
+ assert.equal(new BN('1222222225255589').mod(new BN('611111124969028'))
+ .toString(10), '611111100286561');
+ assert.equal(new BN('-1222222225255589').mod(new BN('611111124969028'))
+ .toString(10), '-611111100286561');
+ assert.equal(new BN('1222222225255589').mod(new BN('-611111124969028'))
+ .toString(10), '611111100286561');
+ assert.equal(new BN('-1222222225255589').mod(new BN('-611111124969028'))
+ .toString(10), '-611111100286561');
+
+ assert.equal(new BN('611111124969028').mod(new BN('1222222225255589'))
+ .toString(10), '611111124969028');
+ assert.equal(new BN('-611111124969028').mod(new BN('1222222225255589'))
+ .toString(10), '-611111124969028');
+ assert.equal(new BN('611111124969028').mod(new BN('-1222222225255589'))
+ .toString(10), '611111124969028');
+ assert.equal(new BN('-611111124969028').mod(new BN('-1222222225255589'))
+ .toString(10), '-611111124969028');
+ });
+
+ it('should mod numbers', function () {
+ assert.equal(new BN('10').mod(new BN(256)).toString(16),
+ 'a');
+ assert.equal(new BN('69527932928').mod(new BN('16974594')).toString(16),
+ '102f302');
+
+ // 178 = 10 * 17 + 8
+ assert.equal(new BN(178).div(new BN(10)).toNumber(), 17);
+ assert.equal(new BN(178).mod(new BN(10)).toNumber(), 8);
+ assert.equal(new BN(178).umod(new BN(10)).toNumber(), 8);
+
+ // -178 = 10 * (-17) + (-8)
+ assert.equal(new BN(-178).div(new BN(10)).toNumber(), -17);
+ assert.equal(new BN(-178).mod(new BN(10)).toNumber(), -8);
+ assert.equal(new BN(-178).umod(new BN(10)).toNumber(), 2);
+
+ // 178 = -10 * (-17) + 8
+ assert.equal(new BN(178).div(new BN(-10)).toNumber(), -17);
+ assert.equal(new BN(178).mod(new BN(-10)).toNumber(), 8);
+ assert.equal(new BN(178).umod(new BN(-10)).toNumber(), 8);
+
+ // -178 = -10 * (17) + (-8)
+ assert.equal(new BN(-178).div(new BN(-10)).toNumber(), 17);
+ assert.equal(new BN(-178).mod(new BN(-10)).toNumber(), -8);
+ assert.equal(new BN(-178).umod(new BN(-10)).toNumber(), 2);
+
+ // -4 = 1 * (-3) + -1
+ assert.equal(new BN(-4).div(new BN(-3)).toNumber(), 1);
+ assert.equal(new BN(-4).mod(new BN(-3)).toNumber(), -1);
+
+ // -4 = -1 * (3) + -1
+ assert.equal(new BN(-4).mod(new BN(3)).toNumber(), -1);
+ // -4 = 1 * (-3) + (-1 + 3)
+ assert.equal(new BN(-4).umod(new BN(-3)).toNumber(), 2);
+
+ var p = new BN(
+ 'ffffffff00000001000000000000000000000000ffffffffffffffffffffffff',
+ 16);
+ var a = new BN(
+ 'fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffff' +
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
+ 16);
+ assert.equal(
+ a.mod(p).toString(16),
+ '0');
+ });
+
+ it('should properly carry the sign inside division', function () {
+ var a = new BN('945304eb96065b2a98b57a48a06ae28d285a71b5', 'hex');
+ var b = new BN(
+ 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe',
+ 'hex');
+
+ assert.equal(a.mul(b).mod(a).cmpn(0), 0);
+ });
+ });
+
+ describe('.modn()', function () {
+ it('should act like .mod() on small numbers', function () {
+ assert.equal(new BN('10', 16).modn(256).toString(16), '10');
+ assert.equal(new BN('100', 16).modn(256).toString(16), '0');
+ assert.equal(new BN('1001', 16).modn(256).toString(16), '1');
+ assert.equal(new BN('100000000001', 16).modn(256).toString(16), '1');
+ assert.equal(new BN('100000000001', 16).modn(257).toString(16),
+ new BN('100000000001', 16).mod(new BN(257)).toString(16));
+ assert.equal(new BN('123456789012', 16).modn(3).toString(16),
+ new BN('123456789012', 16).mod(new BN(3)).toString(16));
+ });
+ });
+
+ describe('.abs()', function () {
+ it('should return absolute value', function () {
+ assert.equal(new BN(0x1001).abs().toString(), '4097');
+ assert.equal(new BN(-0x1001).abs().toString(), '4097');
+ assert.equal(new BN('ffffffff', 16).abs().toString(), '4294967295');
+ });
+ });
+
+ describe('.invm()', function () {
+ it('should invert relatively-prime numbers', function () {
+ var p = new BN(257);
+ var a = new BN(3);
+ var b = a.invm(p);
+ assert.equal(a.mul(b).mod(p).toString(16), '1');
+
+ var p192 = new BN(
+ 'fffffffffffffffffffffffffffffffeffffffffffffffff',
+ 16);
+ a = new BN('deadbeef', 16);
+ b = a.invm(p192);
+ assert.equal(a.mul(b).mod(p192).toString(16), '1');
+
+ // Even base
+ var phi = new BN('872d9b030ba368706b68932cf07a0e0c', 16);
+ var e = new BN(65537);
+ var d = e.invm(phi);
+ assert.equal(e.mul(d).mod(phi).toString(16), '1');
+
+ // Even base (take #2)
+ a = new BN('5');
+ b = new BN('6');
+ var r = a.invm(b);
+ assert.equal(r.mul(a).mod(b).toString(16), '1');
+ });
+ });
+
+ describe('.gcd()', function () {
+ it('should return GCD', function () {
+ assert.equal(new BN(3).gcd(new BN(2)).toString(10), '1');
+ assert.equal(new BN(18).gcd(new BN(12)).toString(10), '6');
+ assert.equal(new BN(-18).gcd(new BN(12)).toString(10), '6');
+ assert.equal(new BN(-18).gcd(new BN(-12)).toString(10), '6');
+ assert.equal(new BN(-18).gcd(new BN(0)).toString(10), '18');
+ assert.equal(new BN(0).gcd(new BN(-18)).toString(10), '18');
+ assert.equal(new BN(2).gcd(new BN(0)).toString(10), '2');
+ assert.equal(new BN(0).gcd(new BN(3)).toString(10), '3');
+ assert.equal(new BN(0).gcd(new BN(0)).toString(10), '0');
+ });
+ });
+
+ describe('.egcd()', function () {
+ it('should return EGCD', function () {
+ assert.equal(new BN(3).egcd(new BN(2)).gcd.toString(10), '1');
+ assert.equal(new BN(18).egcd(new BN(12)).gcd.toString(10), '6');
+ assert.equal(new BN(-18).egcd(new BN(12)).gcd.toString(10), '6');
+ assert.equal(new BN(0).egcd(new BN(12)).gcd.toString(10), '12');
+ });
+ it('should not allow 0 input', function () {
+ assert.throws(function () {
+ new BN(1).egcd(0);
+ }, /^Error: Assertion failed$/);
+ });
+ it('should not allow negative input', function () {
+ assert.throws(function () {
+ new BN(1).egcd(-1);
+ }, /^Error: Assertion failed$/);
+ });
+ });
+
+ describe('BN.max(a, b)', function () {
+ it('should return maximum', function () {
+ assert.equal(BN.max(new BN(3), new BN(2)).toString(16), '3');
+ assert.equal(BN.max(new BN(2), new BN(3)).toString(16), '3');
+ assert.equal(BN.max(new BN(2), new BN(2)).toString(16), '2');
+ assert.equal(BN.max(new BN(2), new BN(-2)).toString(16), '2');
+ });
+ });
+
+ describe('BN.min(a, b)', function () {
+ it('should return minimum', function () {
+ assert.equal(BN.min(new BN(3), new BN(2)).toString(16), '2');
+ assert.equal(BN.min(new BN(2), new BN(3)).toString(16), '2');
+ assert.equal(BN.min(new BN(2), new BN(2)).toString(16), '2');
+ assert.equal(BN.min(new BN(2), new BN(-2)).toString(16), '-2');
+ });
+ });
+
+ describe('BN.ineg', function () {
+ it('shouldn\'t change sign for zero', function () {
+ assert.equal(new BN(0).ineg().toString(10), '0');
+ });
+ });
+});
diff --git a/node_modules/bn.js/test/binary-test.js b/node_modules/bn.js/test/binary-test.js
new file mode 100644
index 000000000..37b6421d0
--- /dev/null
+++ b/node_modules/bn.js/test/binary-test.js
@@ -0,0 +1,233 @@
+/* global describe, it */
+
+var assert = require('assert');
+var BN = require('../').BN;
+
+describe('BN.js/Binary', function () {
+ describe('.shl()', function () {
+ it('should shl numbers', function () {
+ // TODO(indutny): add negative numbers when the time will come
+ assert.equal(new BN('69527932928').shln(13).toString(16),
+ '2060602000000');
+ assert.equal(new BN('69527932928').shln(45).toString(16),
+ '206060200000000000000');
+ });
+
+ it('should ushl numbers', function () {
+ assert.equal(new BN('69527932928').ushln(13).toString(16),
+ '2060602000000');
+ assert.equal(new BN('69527932928').ushln(45).toString(16),
+ '206060200000000000000');
+ });
+ });
+
+ describe('.shr()', function () {
+ it('should shr numbers', function () {
+ // TODO(indutny): add negative numbers when the time will come
+ assert.equal(new BN('69527932928').shrn(13).toString(16),
+ '818180');
+ assert.equal(new BN('69527932928').shrn(17).toString(16),
+ '81818');
+ assert.equal(new BN('69527932928').shrn(256).toString(16),
+ '0');
+ });
+
+ it('should ushr numbers', function () {
+ assert.equal(new BN('69527932928').ushrn(13).toString(16),
+ '818180');
+ assert.equal(new BN('69527932928').ushrn(17).toString(16),
+ '81818');
+ assert.equal(new BN('69527932928').ushrn(256).toString(16),
+ '0');
+ });
+ });
+
+ describe('.bincn()', function () {
+ it('should increment bit', function () {
+ assert.equal(new BN(0).bincn(1).toString(16), '2');
+ assert.equal(new BN(2).bincn(1).toString(16), '4');
+ assert.equal(new BN(2).bincn(1).bincn(1).toString(16),
+ new BN(2).bincn(2).toString(16));
+ assert.equal(new BN(0xffffff).bincn(1).toString(16), '1000001');
+ assert.equal(new BN(2).bincn(63).toString(16),
+ '8000000000000002');
+ });
+ });
+
+ describe('.imaskn()', function () {
+ it('should mask bits in-place', function () {
+ assert.equal(new BN(0).imaskn(1).toString(16), '0');
+ assert.equal(new BN(3).imaskn(1).toString(16), '1');
+ assert.equal(new BN('123456789', 16).imaskn(4).toString(16), '9');
+ assert.equal(new BN('123456789', 16).imaskn(16).toString(16), '6789');
+ assert.equal(new BN('123456789', 16).imaskn(28).toString(16), '3456789');
+ });
+
+ it('should not mask when number is bigger than length', function () {
+ assert.equal(new BN(0xe3).imaskn(56).toString(16), 'e3');
+ assert.equal(new BN(0xe3).imaskn(26).toString(16), 'e3');
+ });
+ });
+
+ describe('.testn()', function () {
+ it('should support test specific bit', function () {
+ [
+ 'ff',
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
+ ].forEach(function (hex) {
+ var bn = new BN(hex, 16);
+ var bl = bn.bitLength();
+
+ for (var i = 0; i < bl; ++i) {
+ assert.equal(bn.testn(i), true);
+ }
+
+ // test off the end
+ assert.equal(bn.testn(bl), false);
+ });
+
+ var xbits = '01111001010111001001000100011101' +
+ '11010011101100011000111001011101' +
+ '10010100111000000001011000111101' +
+ '01011111001111100100011110000010' +
+ '01011010100111010001010011000100' +
+ '01101001011110100001001111100110' +
+ '001110010111';
+
+ var x = new BN(
+ '23478905234580795234378912401239784125643978256123048348957342'
+ );
+ for (var i = 0; i < x.bitLength(); ++i) {
+ assert.equal(x.testn(i), (xbits.charAt(i) === '1'), 'Failed @ bit ' + i);
+ }
+ });
+
+ it('should have short-cuts', function () {
+ var x = new BN('abcd', 16);
+ assert(!x.testn(128));
+ });
+ });
+
+ describe('.and()', function () {
+ it('should and numbers', function () {
+ assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+ .and(new BN('101010101010101010101010101010101010101', 2))
+ .toString(2), '0');
+ });
+
+ it('should and numbers of different limb-length', function () {
+ assert.equal(
+ new BN('abcd0000ffff', 16)
+ .and(new BN('abcd', 16)).toString(16),
+ 'abcd');
+ });
+ });
+
+ describe('.iand()', function () {
+ it('should iand numbers', function () {
+ assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+ .iand(new BN('101010101010101010101010101010101010101', 2))
+ .toString(2), '0');
+ assert.equal(new BN('1000000000000000000000000000000000000001', 2)
+ .iand(new BN('1', 2))
+ .toString(2), '1');
+ assert.equal(new BN('1', 2)
+ .iand(new BN('1000000000000000000000000000000000000001', 2))
+ .toString(2), '1');
+ });
+ });
+
+ describe('.or()', function () {
+ it('should or numbers', function () {
+ assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+ .or(new BN('101010101010101010101010101010101010101', 2))
+ .toString(2), '1111111111111111111111111111111111111111');
+ });
+
+ it('should or numbers of different limb-length', function () {
+ assert.equal(
+ new BN('abcd00000000', 16)
+ .or(new BN('abcd', 16)).toString(16),
+ 'abcd0000abcd');
+ });
+ });
+
+ describe('.ior()', function () {
+ it('should ior numbers', function () {
+ assert.equal(new BN('1010101010101010101010101010101010101010', 2)
+ .ior(new BN('101010101010101010101010101010101010101', 2))
+ .toString(2), '1111111111111111111111111111111111111111');
+ assert.equal(new BN('1000000000000000000000000000000000000000', 2)
+ .ior(new BN('1', 2))
+ .toString(2), '1000000000000000000000000000000000000001');
+ assert.equal(new BN('1', 2)
+ .ior(new BN('1000000000000000000000000000000000000000', 2))
+ .toString(2), '1000000000000000000000000000000000000001');
+ });
+ });
+
+ describe('.xor()', function () {
+ it('should xor numbers', function () {
+ assert.equal(new BN('11001100110011001100110011001100', 2)
+ .xor(new BN('1100110011001100110011001100110', 2))
+ .toString(2), '10101010101010101010101010101010');
+ });
+ });
+
+ describe('.ixor()', function () {
+ it('should ixor numbers', function () {
+ assert.equal(new BN('11001100110011001100110011001100', 2)
+ .ixor(new BN('1100110011001100110011001100110', 2))
+ .toString(2), '10101010101010101010101010101010');
+ assert.equal(new BN('11001100110011001100110011001100', 2)
+ .ixor(new BN('1', 2))
+ .toString(2), '11001100110011001100110011001101');
+ assert.equal(new BN('1', 2)
+ .ixor(new BN('11001100110011001100110011001100', 2))
+ .toString(2), '11001100110011001100110011001101');
+ });
+
+ it('should and numbers of different limb-length', function () {
+ assert.equal(
+ new BN('abcd0000ffff', 16)
+ .xor(new BN('abcd', 16)).toString(16),
+ 'abcd00005432');
+ });
+ });
+
+ describe('.setn()', function () {
+ it('should allow single bits to be set', function () {
+ assert.equal(new BN(0).setn(2, true).toString(2), '100');
+ assert.equal(new BN(0).setn(27, true).toString(2),
+ '1000000000000000000000000000');
+ assert.equal(new BN(0).setn(63, true).toString(16),
+ new BN(1).iushln(63).toString(16));
+ assert.equal(new BN('1000000000000000000000000001', 2).setn(27, false)
+ .toString(2), '1');
+ assert.equal(new BN('101', 2).setn(2, false).toString(2), '1');
+ });
+ });
+
+ describe('.notn()', function () {
+ it('should allow bitwise negation', function () {
+ assert.equal(new BN('111000111', 2).notn(9).toString(2),
+ '111000');
+ assert.equal(new BN('000111000', 2).notn(9).toString(2),
+ '111000111');
+ assert.equal(new BN('111000111', 2).notn(9).toString(2),
+ '111000');
+ assert.equal(new BN('000111000', 2).notn(9).toString(2),
+ '111000111');
+ assert.equal(new BN('111000111', 2).notn(32).toString(2),
+ '11111111111111111111111000111000');
+ assert.equal(new BN('000111000', 2).notn(32).toString(2),
+ '11111111111111111111111111000111');
+ assert.equal(new BN('111000111', 2).notn(68).toString(2),
+ '11111111111111111111111111111111' +
+ '111111111111111111111111111000111000');
+ assert.equal(new BN('000111000', 2).notn(68).toString(2),
+ '11111111111111111111111111111111' +
+ '111111111111111111111111111111000111');
+ });
+ });
+});
diff --git a/node_modules/bn.js/test/constructor-test.js b/node_modules/bn.js/test/constructor-test.js
new file mode 100644
index 000000000..11c7df082
--- /dev/null
+++ b/node_modules/bn.js/test/constructor-test.js
@@ -0,0 +1,149 @@
+/* global describe, it */
+
+var assert = require('assert');
+var BN = require('../').BN;
+
+describe('BN.js/Constructor', function () {
+ describe('with Smi input', function () {
+ it('should accept one limb number', function () {
+ assert.equal(new BN(12345).toString(16), '3039');
+ });
+
+ it('should accept two-limb number', function () {
+ assert.equal(new BN(0x4123456).toString(16), '4123456');
+ });
+
+ it('should accept 52 bits of precision', function () {
+ var num = Math.pow(2, 52);
+ assert.equal(new BN(num, 10).toString(10), num.toString(10));
+ });
+
+ it('should accept max safe integer', function () {
+ var num = Math.pow(2, 53) - 1;
+ assert.equal(new BN(num, 10).toString(10), num.toString(10));
+ });
+
+ it('should not accept an unsafe integer', function () {
+ var num = Math.pow(2, 53);
+
+ assert.throws(function () {
+ return new BN(num, 10);
+ }, /^Error: Assertion failed$/);
+ });
+
+ it('should accept two-limb LE number', function () {
+ assert.equal(new BN(0x4123456, null, 'le').toString(16), '56341204');
+ });
+ });
+
+ describe('with String input', function () {
+ it('should accept base-16', function () {
+ assert.equal(new BN('1A6B765D8CDF', 16).toString(16), '1a6b765d8cdf');
+ assert.equal(new BN('1A6B765D8CDF', 16).toString(), '29048849665247');
+ });
+
+ it('should accept base-hex', function () {
+ assert.equal(new BN('FF', 'hex').toString(), '255');
+ });
+
+ it('should accept base-16 with spaces', function () {
+ var num = 'a89c e5af8724 c0a23e0e 0ff77500';
+ assert.equal(new BN(num, 16).toString(16), num.replace(/ /g, ''));
+ });
+
+ it('should accept long base-16', function () {
+ var num = '123456789abcdef123456789abcdef123456789abcdef';
+ assert.equal(new BN(num, 16).toString(16), num);
+ });
+
+ it('should accept positive base-10', function () {
+ assert.equal(new BN('10654321').toString(), '10654321');
+ assert.equal(new BN('29048849665247').toString(16), '1a6b765d8cdf');
+ });
+
+ it('should accept negative base-10', function () {
+ assert.equal(new BN('-29048849665247').toString(16), '-1a6b765d8cdf');
+ });
+
+ it('should accept long base-10', function () {
+ var num = '10000000000000000';
+ assert.equal(new BN(num).toString(10), num);
+ });
+
+ it('should accept base-2', function () {
+ var base2 = '11111111111111111111111111111111111111111111111111111';
+ assert.equal(new BN(base2, 2).toString(2), base2);
+ });
+
+ it('should accept base-36', function () {
+ var base36 = 'zzZzzzZzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
+ assert.equal(new BN(base36, 36).toString(36), base36.toLowerCase());
+ });
+
+ it('should not overflow limbs during base-10', function () {
+ var num = '65820182292848241686198767302293' +
+ '20890292528855852623664389292032';
+ assert(new BN(num).words[0] < 0x4000000);
+ });
+
+ it('should accept base-16 LE integer', function () {
+ assert.equal(new BN('1A6B765D8CDF', 16, 'le').toString(16),
+ 'df8c5d766b1a');
+ });
+ });
+
+ describe('with Array input', function () {
+ it('should not fail on empty array', function () {
+ assert.equal(new BN([]).toString(16), '0');
+ });
+
+ it('should import/export big endian', function () {
+ assert.equal(new BN([ 1, 2, 3 ]).toString(16), '10203');
+ assert.equal(new BN([ 1, 2, 3, 4 ]).toString(16), '1020304');
+ assert.equal(new BN([ 1, 2, 3, 4, 5 ]).toString(16), '102030405');
+ assert.equal(new BN([ 1, 2, 3, 4, 5, 6, 7, 8 ]).toString(16),
+ '102030405060708');
+ assert.equal(new BN([ 1, 2, 3, 4 ]).toArray().join(','), '1,2,3,4');
+ assert.equal(new BN([ 1, 2, 3, 4, 5, 6, 7, 8 ]).toArray().join(','),
+ '1,2,3,4,5,6,7,8');
+ });
+
+ it('should import little endian', function () {
+ assert.equal(new BN([ 1, 2, 3 ], 10, 'le').toString(16), '30201');
+ assert.equal(new BN([ 1, 2, 3, 4 ], 10, 'le').toString(16), '4030201');
+ assert.equal(new BN([ 1, 2, 3, 4, 5 ], 10, 'le').toString(16),
+ '504030201');
+ assert.equal(new BN([ 1, 2, 3, 4, 5, 6, 7, 8 ], 'le').toString(16),
+ '807060504030201');
+ assert.equal(new BN([ 1, 2, 3, 4 ]).toArray('le').join(','), '4,3,2,1');
+ assert.equal(new BN([ 1, 2, 3, 4, 5, 6, 7, 8 ]).toArray('le').join(','),
+ '8,7,6,5,4,3,2,1');
+ });
+
+ it('should import big endian with implicit base', function () {
+ assert.equal(new BN([ 1, 2, 3, 4, 5 ], 'le').toString(16), '504030201');
+ });
+ });
+
+ // the Array code is able to handle Buffer
+ describe('with Buffer input', function () {
+ it('should not fail on empty Buffer', function () {
+ assert.equal(new BN(new Buffer(0)).toString(16), '0');
+ });
+
+ it('should import/export big endian', function () {
+ assert.equal(new BN(new Buffer('010203', 'hex')).toString(16), '10203');
+ });
+
+ it('should import little endian', function () {
+ assert.equal(new BN(new Buffer('010203', 'hex'), 'le').toString(16), '30201');
+ });
+ });
+
+ describe('with BN input', function () {
+ it('should clone BN', function () {
+ var num = new BN(12345);
+ assert.equal(new BN(num).toString(10), '12345');
+ });
+ });
+});
diff --git a/node_modules/bn.js/test/fixtures.js b/node_modules/bn.js/test/fixtures.js
new file mode 100644
index 000000000..39fd661d4
--- /dev/null
+++ b/node_modules/bn.js/test/fixtures.js
@@ -0,0 +1,264 @@
+exports.dhGroups = {
+ p16: {
+ prime: 'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd1' +
+ '29024e088a67cc74020bbea63b139b22514a08798e3404dd' +
+ 'ef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245' +
+ 'e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed' +
+ 'ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3d' +
+ 'c2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f' +
+ '83655d23dca3ad961c62f356208552bb9ed529077096966d' +
+ '670c354e4abc9804f1746c08ca18217c32905e462e36ce3b' +
+ 'e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9' +
+ 'de2bcbf6955817183995497cea956ae515d2261898fa0510' +
+ '15728e5a8aaac42dad33170d04507a33a85521abdf1cba64' +
+ 'ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7' +
+ 'abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6b' +
+ 'f12ffa06d98a0864d87602733ec86a64521f2b18177b200c' +
+ 'bbe117577a615d6c770988c0bad946e208e24fa074e5ab31' +
+ '43db5bfce0fd108e4b82d120a92108011a723c12a787e6d7' +
+ '88719a10bdba5b2699c327186af4e23c1a946834b6150bda' +
+ '2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6' +
+ '287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed' +
+ '1f612970cee2d7afb81bdd762170481cd0069127d5b05aa9' +
+ '93b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199' +
+ 'ffffffffffffffff',
+ priv: '6d5923e6449122cbbcc1b96093e0b7e4fd3e469f58daddae' +
+ '53b49b20664f4132675df9ce98ae0cfdcac0f4181ccb643b' +
+ '625f98104dcf6f7d8e81961e2cab4b5014895260cb977c7d' +
+ '2f981f8532fb5da60b3676dfe57f293f05d525866053ac7e' +
+ '65abfd19241146e92e64f309a97ef3b529af4d6189fa416c' +
+ '9e1a816c3bdf88e5edf48fbd8233ef9038bb46faa95122c0' +
+ '5a426be72039639cd2d53d37254b3d258960dcb33c255ede' +
+ '20e9d7b4b123c8b4f4b986f53cdd510d042166f7dd7dca98' +
+ '7c39ab36381ba30a5fdd027eb6128d2ef8e5802a2194d422' +
+ 'b05fe6e1cb4817789b923d8636c1ec4b7601c90da3ddc178' +
+ '52f59217ae070d87f2e75cbfb6ff92430ad26a71c8373452' +
+ 'ae1cc5c93350e2d7b87e0acfeba401aaf518580937bf0b6c' +
+ '341f8c49165a47e49ce50853989d07171c00f43dcddddf72' +
+ '94fb9c3f4e1124e98ef656b797ef48974ddcd43a21fa06d0' +
+ '565ae8ce494747ce9e0ea0166e76eb45279e5c6471db7df8' +
+ 'cc88764be29666de9c545e72da36da2f7a352fb17bdeb982' +
+ 'a6dc0193ec4bf00b2e533efd6cd4d46e6fb237b775615576' +
+ 'dd6c7c7bbc087a25e6909d1ebc6e5b38e5c8472c0fc429c6' +
+ 'f17da1838cbcd9bbef57c5b5522fd6053e62ba21fe97c826' +
+ 'd3889d0cc17e5fa00b54d8d9f0f46fb523698af965950f4b' +
+ '941369e180f0aece3870d9335f2301db251595d173902cad' +
+ '394eaa6ffef8be6c',
+ pub: 'd53703b7340bc89bfc47176d351e5cf86d5a18d9662eca3c' +
+ '9759c83b6ccda8859649a5866524d77f79e501db923416ca' +
+ '2636243836d3e6df752defc0fb19cc386e3ae48ad647753f' +
+ 'bf415e2612f8a9fd01efe7aca249589590c7e6a0332630bb' +
+ '29c5b3501265d720213790556f0f1d114a9e2071be3620bd' +
+ '4ee1e8bb96689ac9e226f0a4203025f0267adc273a43582b' +
+ '00b70b490343529eaec4dcff140773cd6654658517f51193' +
+ '13f21f0a8e04fe7d7b21ffeca85ff8f87c42bb8d9cb13a72' +
+ 'c00e9c6e9dfcedda0777af951cc8ccab90d35e915e707d8e' +
+ '4c2aca219547dd78e9a1a0730accdc9ad0b854e51edd1e91' +
+ '4756760bab156ca6e3cb9c625cf0870def34e9ac2e552800' +
+ 'd6ce506d43dbbc75acfa0c8d8fb12daa3c783fb726f187d5' +
+ '58131779239c912d389d0511e0f3a81969d12aeee670e48f' +
+ 'ba41f7ed9f10705543689c2506b976a8ffabed45e33795b0' +
+ '1df4f6b993a33d1deab1316a67419afa31fbb6fdd252ee8c' +
+ '7c7d1d016c44e3fcf6b41898d7f206aa33760b505e4eff2e' +
+ 'c624bc7fe636b1d59e45d6f904fc391419f13d1f0cdb5b6c' +
+ '2378b09434159917dde709f8a6b5dc30994d056e3f964371' +
+ '11587ac7af0a442b8367a7bd940f752ddabf31cf01171e24' +
+ 'd78df136e9681cd974ce4f858a5fb6efd3234a91857bb52d' +
+ '9e7b414a8bc66db4b5a73bbeccfb6eb764b4f0cbf0375136' +
+ 'b024b04e698d54a5'
+ },
+ p17: {
+ prime: 'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd1' +
+ '29024e088a67cc74020bbea63b139b22514a08798e3404dd' +
+ 'ef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245' +
+ 'e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed' +
+ 'ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3d' +
+ 'c2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f' +
+ '83655d23dca3ad961c62f356208552bb9ed529077096966d' +
+ '670c354e4abc9804f1746c08ca18217c32905e462e36ce3b' +
+ 'e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9' +
+ 'de2bcbf6955817183995497cea956ae515d2261898fa0510' +
+ '15728e5a8aaac42dad33170d04507a33a85521abdf1cba64' +
+ 'ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7' +
+ 'abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6b' +
+ 'f12ffa06d98a0864d87602733ec86a64521f2b18177b200c' +
+ 'bbe117577a615d6c770988c0bad946e208e24fa074e5ab31' +
+ '43db5bfce0fd108e4b82d120a92108011a723c12a787e6d7' +
+ '88719a10bdba5b2699c327186af4e23c1a946834b6150bda' +
+ '2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6' +
+ '287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed' +
+ '1f612970cee2d7afb81bdd762170481cd0069127d5b05aa9' +
+ '93b4ea988d8fddc186ffb7dc90a6c08f4df435c934028492' +
+ '36c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bd' +
+ 'f8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831' +
+ '179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1b' +
+ 'db7f1447e6cc254b332051512bd7af426fb8f401378cd2bf' +
+ '5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6' +
+ 'd55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f3' +
+ '23a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aa' +
+ 'cc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be328' +
+ '06a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55c' +
+ 'da56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee' +
+ '12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff',
+ priv: '6017f2bc23e1caff5b0a8b4e1fc72422b5204415787801dc' +
+ '025762b8dbb98ab57603aaaa27c4e6bdf742b4a1726b9375' +
+ 'a8ca3cf07771779589831d8bd18ddeb79c43e7e77d433950' +
+ 'e652e49df35b11fa09644874d71d62fdaffb580816c2c88c' +
+ '2c4a2eefd4a660360316741b05a15a2e37f236692ad3c463' +
+ 'fff559938fc6b77176e84e1bb47fb41af691c5eb7bb81bd8' +
+ 'c918f52625a1128f754b08f5a1403b84667231c4dfe07ed4' +
+ '326234c113931ce606037e960f35a2dfdec38a5f057884d3' +
+ '0af8fab3be39c1eeb390205fd65982191fc21d5aa30ddf51' +
+ 'a8e1c58c0c19fc4b4a7380ea9e836aaf671c90c29bc4bcc7' +
+ '813811aa436a7a9005de9b507957c56a9caa1351b6efc620' +
+ '7225a18f6e97f830fb6a8c4f03b82f4611e67ab9497b9271' +
+ 'd6ac252793cc3e5538990dbd894d2dbc2d152801937d9f74' +
+ 'da4b741b50b4d40e4c75e2ac163f7b397fd555648b249f97' +
+ 'ffe58ffb6d096aa84534c4c5729cff137759bd34e80db4ab' +
+ '47e2b9c52064e7f0bf677f72ac9e5d0c6606943683f9d12f' +
+ '180cf065a5cb8ec3179a874f358847a907f8471d15f1e728' +
+ '7023249d6d13c82da52628654438f47b8b5cdf4761fbf6ad' +
+ '9219eceac657dbd06cf2ab776ad4c968f81c3d039367f0a4' +
+ 'd77c7ec4435c27b6c147071665100063b5666e06eb2fb2cc' +
+ '3159ba34bc98ca346342195f6f1fb053ddc3bc1873564d40' +
+ '1c6738cdf764d6e1ff25ca5926f80102ea6593c17170966b' +
+ 'b5d7352dd7fb821230237ea3ebed1f920feaadbd21be295a' +
+ '69f2083deae9c5cdf5f4830eb04b7c1f80cc61c17232d79f' +
+ '7ecc2cc462a7965f804001c89982734e5abba2d31df1b012' +
+ '152c6b226dff34510b54be8c2cd68d795def66c57a3abfb6' +
+ '896f1d139e633417f8c694764974d268f46ece3a8d6616ea' +
+ 'a592144be48ee1e0a1595d3e5edfede5b27cec6c48ceb2ff' +
+ 'b42cb44275851b0ebf87dfc9aa2d0cb0805e9454b051dfe8' +
+ 'a29fadd82491a4b4c23f2d06ba45483ab59976da1433c9ce' +
+ '500164b957a04cf62dd67595319b512fc4b998424d1164dd' +
+ 'bbe5d1a0f7257cbb04ec9b5ed92079a1502d98725023ecb2',
+ pub: '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +
+ '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +
+ 'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +
+ 'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +
+ 'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +
+ 'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +
+ 'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +
+ '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +
+ 'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +
+ '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +
+ '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +
+ '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +
+ 'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +
+ '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +
+ 'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +
+ '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +
+ '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +
+ 'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +
+ 'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +
+ '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +
+ 'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +
+ '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +
+ 'fbedccbc786951025597522eef283e3f56b44561a0765783' +
+ '420128638c257e54b972a76e4261892d81222b3e2039c61a' +
+ 'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +
+ 'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +
+ '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +
+ 'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +
+ 'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +
+ '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +
+ 'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +
+ '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d',
+ q: 'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +
+ '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +
+ '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +
+ 'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +
+ 'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +
+ 'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +
+ 'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +
+ 'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +
+ '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +
+ '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +
+ 'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +
+ 'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +
+ '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +
+ 'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +
+ 'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +
+ '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +
+ '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +
+ '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +
+ '100050a430b47bc592995606440272a4994677577a6aaa1b' +
+ 'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +
+ 'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +
+ '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +
+ 'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +
+ '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +
+ '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +
+ '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +
+ '1c64145849b3da8c2d343410df892d958db232617f9896f1' +
+ 'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +
+ 'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +
+ 'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +
+ 'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +
+ '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0',
+ qs: '6f0a2fb763eaeb8eb324d564f03d4a55fdcd709e5f1b65e9' +
+ '5702b0141182f9f945d71bc3e64a7dfdae7482a7dd5a4e58' +
+ 'bc38f78de2013f2c468a621f08536969d2c8d011bb3bc259' +
+ '2124692c91140a5472cad224acdacdeae5751dadfdf068b8' +
+ '77bfa7374694c6a7be159fc3d24ff9eeeecaf62580427ad8' +
+ '622d48c51a1c4b1701d768c79d8c819776e096d2694107a2' +
+ 'f3ec0c32224795b59d32894834039dacb369280afb221bc0' +
+ '90570a93cf409889b818bb30cccee98b2aa26dbba0f28499' +
+ '08e1a3cd43fa1f1fb71049e5c77c3724d74dc351d9989057' +
+ '37bbda3805bd6b1293da8774410fb66e3194e18cdb304dd9' +
+ 'a0b59b583dcbc9fc045ac9d56aea5cfc9f8a0b95da1e11b7' +
+ '574d1f976e45fe12294997fac66ca0b83fc056183549e850' +
+ 'a11413cc4abbe39a211e8c8cbf82f2a23266b3c10ab9e286' +
+ '07a1b6088909cddff856e1eb6b2cde8bdac53fa939827736' +
+ 'ca1b892f6c95899613442bd02dbdb747f02487718e2d3f22' +
+ 'f73734d29767ed8d0e346d0c4098b6fdcb4df7d0c4d29603' +
+ '5bffe80d6c65ae0a1b814150d349096baaf950f2caf298d2' +
+ 'b292a1d48cf82b10734fe8cedfa16914076dfe3e9b51337b' +
+ 'ed28ea1e6824bb717b641ca0e526e175d3e5ed7892aebab0' +
+ 'f207562cc938a821e2956107c09b6ce4049adddcd0b7505d' +
+ '49ae6c69a20122461102d465d93dc03db026be54c303613a' +
+ 'b8e5ce3fd4f65d0b6162ff740a0bf5469ffd442d8c509cd2' +
+ '3b40dab90f6776ca17fc0678774bd6eee1fa85ababa52ec1' +
+ 'a15031eb677c6c488661dddd8b83d6031fe294489ded5f08' +
+ '8ad1689a14baeae7e688afa3033899c81f58de39b392ca94' +
+ 'af6f15a46f19fa95c06f9493c8b96a9be25e78b9ea35013b' +
+ 'caa76de6303939299d07426a88a334278fc3d0d9fa71373e' +
+ 'be51d3c1076ab93a11d3d0d703366ff8cde4c11261d488e5' +
+ '60a2bdf3bfe2476032294800d6a4a39d306e65c6d7d8d66e' +
+ '5ec63eee94531e83a9bddc458a2b508285c0ee10b7bd94da' +
+ '2815a0c5bd5b2e15cbe66355e42f5af8955cdfc0b3a4996d' +
+ '288db1f4b32b15643b18193e378cb7491f3c3951cdd044b1' +
+ 'a519571bffac2da986f5f1d506c66530a55f70751e24fa8e' +
+ 'd83ac2347f4069fb561a5565e78c6f0207da24e889a93a96' +
+ '65f717d9fe8a2938a09ab5f81be7ccecf466c0397fc15a57' +
+ '469939793f302739765773c256a3ca55d0548afd117a7cae' +
+ '98ca7e0d749a130c7b743d376848e255f8fdbe4cb4480b63' +
+ 'cd2c015d1020cf095d175f3ca9dcdfbaf1b2a6e6468eee4c' +
+ 'c750f2132a77f376bd9782b9d0ff4da98621b898e251a263' +
+ '4301ba2214a8c430b2f7a79dbbfd6d7ff6e9b0c137b025ff' +
+ '587c0bf912f0b19d4fff96b1ecd2ca990c89b386055c60f2' +
+ '3b94214bd55096f17a7b2c0fa12b333235101cd6f28a128c' +
+ '782e8a72671adadebbd073ded30bd7f09fb693565dcf0bf3' +
+ '090c21d13e5b0989dd8956f18f17f4f69449a13549c9d80a' +
+ '77e5e61b5aeeee9528634100e7bc390672f0ded1ca53555b' +
+ 'abddbcf700b9da6192255bddf50a76b709fbed251dce4c7e' +
+ '1ca36b85d1e97c1bc9d38c887a5adf140f9eeef674c31422' +
+ 'e65f63cae719f8c1324e42fa5fd8500899ef5aa3f9856aa7' +
+ 'ce10c85600a040343204f36bfeab8cfa6e9deb8a2edd2a8e' +
+ '018d00c7c9fa3a251ad0f57183c37e6377797653f382ec7a' +
+ '2b0145e16d3c856bc3634b46d90d7198aff12aff88a30e34' +
+ 'e2bfaf62705f3382576a9d3eeb0829fca2387b5b654af46e' +
+ '5cf6316fb57d59e5ea6c369061ac64d99671b0e516529dd5' +
+ 'd9c48ea0503e55fee090d36c5ea8b5954f6fcc0060794e1c' +
+ 'b7bc24aa1e5c0142fd4ce6e8fd5aa92a7bf84317ea9e1642' +
+ 'b6995bac6705adf93cbce72433ed0871139970d640f67b78' +
+ 'e63a7a6d849db2567df69ac7d79f8c62664ac221df228289' +
+ 'd0a4f9ebd9acb4f87d49da64e51a619fd3f3baccbd9feb12' +
+ '5abe0cc2c8d17ed1d8546da2b6c641f4d3020a5f9b9f26ac' +
+ '16546c2d61385505612275ea344c2bbf1ce890023738f715' +
+ '5e9eba6a071678c8ebd009c328c3eb643679de86e69a9fa5' +
+ '67a9e146030ff03d546310a0a568c5ba0070e0da22f2cef8' +
+ '54714b04d399bbc8fd261f9e8efcd0e83bdbc3f5cfb2d024' +
+ '3e398478cc598e000124eb8858f9df8f52946c2a1ca5c400'
+ }
+};
diff --git a/node_modules/bn.js/test/pummel/dh-group-test.js b/node_modules/bn.js/test/pummel/dh-group-test.js
new file mode 100644
index 000000000..37a259ffa
--- /dev/null
+++ b/node_modules/bn.js/test/pummel/dh-group-test.js
@@ -0,0 +1,23 @@
+/* global describe, it */
+
+var assert = require('assert');
+var BN = require('../../').BN;
+var fixtures = require('../fixtures');
+
+describe('BN.js/Slow DH test', function () {
+ var groups = fixtures.dhGroups;
+ Object.keys(groups).forEach(function (name) {
+ it('should match public key for ' + name + ' group', function () {
+ var group = groups[name];
+
+ this.timeout(3600 * 1000);
+
+ var base = new BN(2);
+ var mont = BN.red(new BN(group.prime, 16));
+ var priv = new BN(group.priv, 16);
+ var multed = base.toRed(mont).redPow(priv).fromRed();
+ var actual = new Buffer(multed.toArray());
+ assert.equal(actual.toString('hex'), group.pub);
+ });
+ });
+});
diff --git a/node_modules/bn.js/test/red-test.js b/node_modules/bn.js/test/red-test.js
new file mode 100644
index 000000000..fc2498c93
--- /dev/null
+++ b/node_modules/bn.js/test/red-test.js
@@ -0,0 +1,263 @@
+/* global describe, it */
+
+var assert = require('assert');
+var BN = require('../').BN;
+
+describe('BN.js/Reduction context', function () {
+ function testMethod (name, fn) {
+ describe(name + ' method', function () {
+ it('should support add, iadd, sub, isub operations', function () {
+ var p = new BN(257);
+ var m = fn(p);
+ var a = new BN(123).toRed(m);
+ var b = new BN(231).toRed(m);
+
+ assert.equal(a.redAdd(b).fromRed().toString(10), '97');
+ assert.equal(a.redSub(b).fromRed().toString(10), '149');
+ assert.equal(b.redSub(a).fromRed().toString(10), '108');
+
+ assert.equal(a.clone().redIAdd(b).fromRed().toString(10), '97');
+ assert.equal(a.clone().redISub(b).fromRed().toString(10), '149');
+ assert.equal(b.clone().redISub(a).fromRed().toString(10), '108');
+ });
+
+ it('should support pow and mul operations', function () {
+ var p192 = new BN(
+ 'fffffffffffffffffffffffffffffffeffffffffffffffff',
+ 16);
+ var m = fn(p192);
+ var a = new BN(123);
+ var b = new BN(231);
+ var c = a.toRed(m).redMul(b.toRed(m)).fromRed();
+ assert(c.cmp(a.mul(b).mod(p192)) === 0);
+
+ assert.equal(a.toRed(m).redPow(new BN(3)).fromRed()
+ .cmp(a.sqr().mul(a)), 0);
+ assert.equal(a.toRed(m).redPow(new BN(4)).fromRed()
+ .cmp(a.sqr().sqr()), 0);
+ assert.equal(a.toRed(m).redPow(new BN(8)).fromRed()
+ .cmp(a.sqr().sqr().sqr()), 0);
+ assert.equal(a.toRed(m).redPow(new BN(9)).fromRed()
+ .cmp(a.sqr().sqr().sqr().mul(a)), 0);
+ assert.equal(a.toRed(m).redPow(new BN(17)).fromRed()
+ .cmp(a.sqr().sqr().sqr().sqr().mul(a)), 0);
+ assert.equal(
+ a.toRed(m).redPow(new BN('deadbeefabbadead', 16)).fromRed()
+ .toString(16),
+ '3aa0e7e304e320b68ef61592bcb00341866d6fa66e11a4d6');
+ });
+
+ it('should sqrtm numbers', function () {
+ var p = new BN(263);
+ var m = fn(p);
+ var q = new BN(11).toRed(m);
+
+ var qr = q.redSqrt();
+ assert.equal(qr.redSqr().cmp(q), 0);
+
+ qr = q.redSqrt();
+ assert.equal(qr.redSqr().cmp(q), 0);
+
+ p = new BN(
+ 'fffffffffffffffffffffffffffffffeffffffffffffffff',
+ 16);
+ m = fn(p);
+
+ q = new BN(13).toRed(m);
+ qr = q.redSqrt(true, p);
+ assert.equal(qr.redSqr().cmp(q), 0);
+
+ qr = q.redSqrt(false, p);
+ assert.equal(qr.redSqr().cmp(q), 0);
+
+ // Tonelli-shanks
+ p = new BN(13);
+ m = fn(p);
+ q = new BN(10).toRed(m);
+ assert.equal(q.redSqrt().fromRed().toString(10), '7');
+ });
+
+ it('should invm numbers', function () {
+ var p = new BN(257);
+ var m = fn(p);
+ var a = new BN(3).toRed(m);
+ var b = a.redInvm();
+ assert.equal(a.redMul(b).fromRed().toString(16), '1');
+ });
+
+ it('should invm numbers (regression)', function () {
+ var p = new BN(
+ 'ffffffff00000001000000000000000000000000ffffffffffffffffffffffff',
+ 16);
+ var a = new BN(
+ 'e1d969b8192fbac73ea5b7921896d6a2263d4d4077bb8e5055361d1f7f8163f3',
+ 16);
+
+ var m = fn(p);
+ a = a.toRed(m);
+
+ assert.equal(a.redInvm().fromRed().negative, 0);
+ });
+
+ it('should imul numbers', function () {
+ var p = new BN(
+ 'fffffffffffffffffffffffffffffffeffffffffffffffff',
+ 16);
+ var m = fn(p);
+
+ var a = new BN('deadbeefabbadead', 16);
+ var b = new BN('abbadeadbeefdead', 16);
+ var c = a.mul(b).mod(p);
+
+ assert.equal(a.toRed(m).redIMul(b.toRed(m)).fromRed().toString(16),
+ c.toString(16));
+ });
+
+ it('should pow(base, 0) == 1', function () {
+ var base = new BN(256).toRed(BN.red('k256'));
+ var exponent = new BN(0);
+ var result = base.redPow(exponent);
+ assert.equal(result.toString(), '1');
+ });
+
+ it('should shl numbers', function () {
+ var base = new BN(256).toRed(BN.red('k256'));
+ var result = base.redShl(1);
+ assert.equal(result.toString(), '512');
+ });
+
+ it('should reduce when converting to red', function () {
+ var p = new BN(257);
+ var m = fn(p);
+ var a = new BN(5).toRed(m);
+
+ assert.doesNotThrow(function () {
+ var b = a.redISub(new BN(512).toRed(m));
+ b.redISub(new BN(512).toRed(m));
+ });
+ });
+
+ it('redNeg and zero value', function () {
+ var a = new BN(0).toRed(BN.red('k256')).redNeg();
+ assert.equal(a.isZero(), true);
+ });
+
+ it('should not allow modulus <= 1', function () {
+ assert.throws(function () {
+ BN.red(new BN(0));
+ }, /^Error: modulus must be greater than 1$/);
+
+ assert.throws(function () {
+ BN.red(new BN(1));
+ }, /^Error: modulus must be greater than 1$/);
+
+ assert.doesNotThrow(function () {
+ BN.red(new BN(2));
+ });
+ });
+ });
+ }
+
+ testMethod('Plain', BN.red);
+ testMethod('Montgomery', BN.mont);
+
+ describe('Pseudo-Mersenne Primes', function () {
+ it('should reduce numbers mod k256', function () {
+ var p = BN._prime('k256');
+
+ assert.equal(p.ireduce(new BN(0xdead)).toString(16), 'dead');
+ assert.equal(p.ireduce(new BN('deadbeef', 16)).toString(16), 'deadbeef');
+
+ var num = new BN('fedcba9876543210fedcba9876543210dead' +
+ 'fedcba9876543210fedcba9876543210dead',
+ 16);
+ var exp = num.mod(p.p).toString(16);
+ assert.equal(p.ireduce(num).toString(16), exp);
+
+ var regr = new BN('f7e46df64c1815962bf7bc9c56128798' +
+ '3f4fcef9cb1979573163b477eab93959' +
+ '335dfb29ef07a4d835d22aa3b6797760' +
+ '70a8b8f59ba73d56d01a79af9',
+ 16);
+ exp = regr.mod(p.p).toString(16);
+
+ assert.equal(p.ireduce(regr).toString(16), exp);
+ });
+
+ it('should not fail to invm number mod k256', function () {
+ var regr2 = new BN(
+ '6c150c4aa9a8cf1934485d40674d4a7cd494675537bda36d49405c5d2c6f496f', 16);
+ regr2 = regr2.toRed(BN.red('k256'));
+ assert.equal(regr2.redInvm().redMul(regr2).fromRed().cmpn(1), 0);
+ });
+
+ it('should correctly square the number', function () {
+ var p = BN._prime('k256').p;
+ var red = BN.red('k256');
+
+ var n = new BN('9cd8cb48c3281596139f147c1364a3ed' +
+ 'e88d3f310fdb0eb98c924e599ca1b3c9',
+ 16);
+ var expected = n.sqr().mod(p);
+ var actual = n.toRed(red).redSqr().fromRed();
+
+ assert.equal(actual.toString(16), expected.toString(16));
+ });
+
+ it('redISqr should return right result', function () {
+ var n = new BN('30f28939', 16);
+ var actual = n.toRed(BN.red('k256')).redISqr().fromRed();
+ assert.equal(actual.toString(16), '95bd93d19520eb1');
+ });
+ });
+
+ it('should avoid 4.1.0 regresion', function () {
+ function bits2int (obits, q) {
+ var bits = new BN(obits);
+ var shift = (obits.length << 3) - q.bitLength();
+ if (shift > 0) {
+ bits.ishrn(shift);
+ }
+ return bits;
+ }
+ var t = new Buffer('aff1651e4cd6036d57aa8b2a05ccf1a9d5a40166340ecbbdc55' +
+ 'be10b568aa0aa3d05ce9a2fcec9df8ed018e29683c6051cb83e' +
+ '46ce31ba4edb045356a8d0d80b', 'hex');
+ var g = new BN('5c7ff6b06f8f143fe8288433493e4769c4d988ace5be25a0e24809670' +
+ '716c613d7b0cee6932f8faa7c44d2cb24523da53fbe4f6ec3595892d1' +
+ 'aa58c4328a06c46a15662e7eaa703a1decf8bbb2d05dbe2eb956c142a' +
+ '338661d10461c0d135472085057f3494309ffa73c611f78b32adbb574' +
+ '0c361c9f35be90997db2014e2ef5aa61782f52abeb8bd6432c4dd097b' +
+ 'c5423b285dafb60dc364e8161f4a2a35aca3a10b1c4d203cc76a470a3' +
+ '3afdcbdd92959859abd8b56e1725252d78eac66e71ba9ae3f1dd24871' +
+ '99874393cd4d832186800654760e1e34c09e4d155179f9ec0dc4473f9' +
+ '96bdce6eed1cabed8b6f116f7ad9cf505df0f998e34ab27514b0ffe7',
+ 16);
+ var p = new BN('9db6fb5951b66bb6fe1e140f1d2ce5502374161fd6538df1648218642' +
+ 'f0b5c48c8f7a41aadfa187324b87674fa1822b00f1ecf8136943d7c55' +
+ '757264e5a1a44ffe012e9936e00c1d3e9310b01c7d179805d3058b2a9' +
+ 'f4bb6f9716bfe6117c6b5b3cc4d9be341104ad4a80ad6c94e005f4b99' +
+ '3e14f091eb51743bf33050c38de235567e1b34c3d6a5c0ceaa1a0f368' +
+ '213c3d19843d0b4b09dcb9fc72d39c8de41f1bf14d4bb4563ca283716' +
+ '21cad3324b6a2d392145bebfac748805236f5ca2fe92b871cd8f9c36d' +
+ '3292b5509ca8caa77a2adfc7bfd77dda6f71125a7456fea153e433256' +
+ 'a2261c6a06ed3693797e7995fad5aabbcfbe3eda2741e375404ae25b',
+ 16);
+ var q = new BN('f2c3119374ce76c9356990b465374a17f23f9ed35089bd969f61c6dde' +
+ '9998c1f', 16);
+ var k = bits2int(t, q);
+ var expectedR = '89ec4bb1400eccff8e7d9aa515cd1de7803f2daff09693ee7fd1353e' +
+ '90a68307';
+ var r = g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q);
+ assert.equal(r.toString(16), expectedR);
+ });
+
+ it('K256.split for 512 bits number should return equal numbers', function () {
+ var red = BN.red('k256');
+ var input = new BN(1).iushln(512).subn(1);
+ assert.equal(input.bitLength(), 512);
+ var output = new BN(0);
+ red.prime.split(input, output);
+ assert.equal(input.cmp(output), 0);
+ });
+});
diff --git a/node_modules/bn.js/test/utils-test.js b/node_modules/bn.js/test/utils-test.js
new file mode 100644
index 000000000..8571905ad
--- /dev/null
+++ b/node_modules/bn.js/test/utils-test.js
@@ -0,0 +1,345 @@
+/* global describe, it */
+
+var assert = require('assert');
+var BN = require('../').BN;
+
+describe('BN.js/Utils', function () {
+ describe('.toString()', function () {
+ describe('binary padding', function () {
+ it('should have a length of 256', function () {
+ var a = new BN(0);
+
+ assert.equal(a.toString(2, 256).length, 256);
+ });
+ });
+ describe('hex padding', function () {
+ it('should have length of 8 from leading 15', function () {
+ var a = new BN('ffb9602', 16);
+
+ assert.equal(a.toString('hex', 2).length, 8);
+ });
+
+ it('should have length of 8 from leading zero', function () {
+ var a = new BN('fb9604', 16);
+
+ assert.equal(a.toString('hex', 8).length, 8);
+ });
+
+ it('should have length of 8 from leading zeros', function () {
+ var a = new BN(0);
+
+ assert.equal(a.toString('hex', 8).length, 8);
+ });
+
+ it('should have length of 64 from leading 15', function () {
+ var a = new BN(
+ 'ffb96ff654e61130ba8422f0debca77a0ea74ae5ea8bca9b54ab64aabf01003',
+ 16);
+
+ assert.equal(a.toString('hex', 2).length, 64);
+ });
+
+ it('should have length of 64 from leading zero', function () {
+ var a = new BN(
+ 'fb96ff654e61130ba8422f0debca77a0ea74ae5ea8bca9b54ab64aabf01003',
+ 16);
+
+ assert.equal(a.toString('hex', 64).length, 64);
+ });
+ });
+ });
+
+ describe('.isNeg()', function () {
+ it('should return true for negative numbers', function () {
+ assert.equal(new BN(-1).isNeg(), true);
+ assert.equal(new BN(1).isNeg(), false);
+ assert.equal(new BN(0).isNeg(), false);
+ assert.equal(new BN('-0', 10).isNeg(), false);
+ });
+ });
+
+ describe('.isOdd()', function () {
+ it('should return true for odd numbers', function () {
+ assert.equal(new BN(0).isOdd(), false);
+ assert.equal(new BN(1).isOdd(), true);
+ assert.equal(new BN(2).isOdd(), false);
+ assert.equal(new BN('-0', 10).isOdd(), false);
+ assert.equal(new BN('-1', 10).isOdd(), true);
+ assert.equal(new BN('-2', 10).isOdd(), false);
+ });
+ });
+
+ describe('.isEven()', function () {
+ it('should return true for even numbers', function () {
+ assert.equal(new BN(0).isEven(), true);
+ assert.equal(new BN(1).isEven(), false);
+ assert.equal(new BN(2).isEven(), true);
+ assert.equal(new BN('-0', 10).isEven(), true);
+ assert.equal(new BN('-1', 10).isEven(), false);
+ assert.equal(new BN('-2', 10).isEven(), true);
+ });
+ });
+
+ describe('.isZero()', function () {
+ it('should return true for zero', function () {
+ assert.equal(new BN(0).isZero(), true);
+ assert.equal(new BN(1).isZero(), false);
+ assert.equal(new BN(0xffffffff).isZero(), false);
+ });
+ });
+
+ describe('.bitLength()', function () {
+ it('should return proper bitLength', function () {
+ assert.equal(new BN(0).bitLength(), 0);
+ assert.equal(new BN(0x1).bitLength(), 1);
+ assert.equal(new BN(0x2).bitLength(), 2);
+ assert.equal(new BN(0x3).bitLength(), 2);
+ assert.equal(new BN(0x4).bitLength(), 3);
+ assert.equal(new BN(0x8).bitLength(), 4);
+ assert.equal(new BN(0x10).bitLength(), 5);
+ assert.equal(new BN(0x100).bitLength(), 9);
+ assert.equal(new BN(0x123456).bitLength(), 21);
+ assert.equal(new BN('123456789', 16).bitLength(), 33);
+ assert.equal(new BN('8023456789', 16).bitLength(), 40);
+ });
+ });
+
+ describe('.byteLength()', function () {
+ it('should return proper byteLength', function () {
+ assert.equal(new BN(0).byteLength(), 0);
+ assert.equal(new BN(0x1).byteLength(), 1);
+ assert.equal(new BN(0x2).byteLength(), 1);
+ assert.equal(new BN(0x3).byteLength(), 1);
+ assert.equal(new BN(0x4).byteLength(), 1);
+ assert.equal(new BN(0x8).byteLength(), 1);
+ assert.equal(new BN(0x10).byteLength(), 1);
+ assert.equal(new BN(0x100).byteLength(), 2);
+ assert.equal(new BN(0x123456).byteLength(), 3);
+ assert.equal(new BN('123456789', 16).byteLength(), 5);
+ assert.equal(new BN('8023456789', 16).byteLength(), 5);
+ });
+ });
+
+ describe('.toArray()', function () {
+ it('should return [ 0 ] for `0`', function () {
+ var n = new BN(0);
+ assert.deepEqual(n.toArray('be'), [ 0 ]);
+ assert.deepEqual(n.toArray('le'), [ 0 ]);
+ });
+
+ it('should zero pad to desired lengths', function () {
+ var n = new BN(0x123456);
+ assert.deepEqual(n.toArray('be', 5), [ 0x00, 0x00, 0x12, 0x34, 0x56 ]);
+ assert.deepEqual(n.toArray('le', 5), [ 0x56, 0x34, 0x12, 0x00, 0x00 ]);
+ });
+
+ it('should throw when naturally larger than desired length', function () {
+ var n = new BN(0x123456);
+ assert.throws(function () {
+ n.toArray('be', 2);
+ }, /^Error: byte array longer than desired length$/);
+ });
+ });
+
+ describe('.toBuffer', function () {
+ it('should return proper Buffer', function () {
+ var n = new BN(0x123456);
+ assert.deepEqual(n.toBuffer('be', 5).toString('hex'), '0000123456');
+ assert.deepEqual(n.toBuffer('le', 5).toString('hex'), '5634120000');
+ });
+ });
+
+ describe('.toNumber()', function () {
+ it('should return proper Number if below the limit', function () {
+ assert.deepEqual(new BN(0x123456).toNumber(), 0x123456);
+ assert.deepEqual(new BN(0x3ffffff).toNumber(), 0x3ffffff);
+ assert.deepEqual(new BN(0x4000000).toNumber(), 0x4000000);
+ assert.deepEqual(new BN(0x10000000000000).toNumber(), 0x10000000000000);
+ assert.deepEqual(new BN(0x10040004004000).toNumber(), 0x10040004004000);
+ assert.deepEqual(new BN(-0x123456).toNumber(), -0x123456);
+ assert.deepEqual(new BN(-0x3ffffff).toNumber(), -0x3ffffff);
+ assert.deepEqual(new BN(-0x4000000).toNumber(), -0x4000000);
+ assert.deepEqual(new BN(-0x10000000000000).toNumber(), -0x10000000000000);
+ assert.deepEqual(new BN(-0x10040004004000).toNumber(), -0x10040004004000);
+ });
+
+ it('should throw when number exceeds 53 bits', function () {
+ var n = new BN(1).iushln(54);
+ assert.throws(function () {
+ n.toNumber();
+ }, /^Error: Number can only safely store up to 53 bits$/);
+ });
+ });
+
+ describe('.zeroBits()', function () {
+ it('should return proper zeroBits', function () {
+ assert.equal(new BN(0).zeroBits(), 0);
+ assert.equal(new BN(0x1).zeroBits(), 0);
+ assert.equal(new BN(0x2).zeroBits(), 1);
+ assert.equal(new BN(0x3).zeroBits(), 0);
+ assert.equal(new BN(0x4).zeroBits(), 2);
+ assert.equal(new BN(0x8).zeroBits(), 3);
+ assert.equal(new BN(0x10).zeroBits(), 4);
+ assert.equal(new BN(0x100).zeroBits(), 8);
+ assert.equal(new BN(0x1000000).zeroBits(), 24);
+ assert.equal(new BN(0x123456).zeroBits(), 1);
+ });
+ });
+
+ describe('.toJSON', function () {
+ it('should return hex string', function () {
+ assert.equal(new BN(0x123).toJSON(), '123');
+ });
+ });
+
+ describe('.cmpn', function () {
+ it('should return -1, 0, 1 correctly', function () {
+ assert.equal(new BN(42).cmpn(42), 0);
+ assert.equal(new BN(42).cmpn(43), -1);
+ assert.equal(new BN(42).cmpn(41), 1);
+ assert.equal(new BN(0x3fffffe).cmpn(0x3fffffe), 0);
+ assert.equal(new BN(0x3fffffe).cmpn(0x3ffffff), -1);
+ assert.equal(new BN(0x3fffffe).cmpn(0x3fffffd), 1);
+ assert.throws(function () {
+ new BN(0x3fffffe).cmpn(0x4000000);
+ }, /^Error: Number is too big$/);
+ assert.equal(new BN(42).cmpn(-42), 1);
+ assert.equal(new BN(-42).cmpn(42), -1);
+ assert.equal(new BN(-42).cmpn(-42), 0);
+ assert.equal(1 / new BN(-42).cmpn(-42), Infinity);
+ });
+ });
+
+ describe('.cmp', function () {
+ it('should return -1, 0, 1 correctly', function () {
+ assert.equal(new BN(42).cmp(new BN(42)), 0);
+ assert.equal(new BN(42).cmp(new BN(43)), -1);
+ assert.equal(new BN(42).cmp(new BN(41)), 1);
+ assert.equal(new BN(0x3fffffe).cmp(new BN(0x3fffffe)), 0);
+ assert.equal(new BN(0x3fffffe).cmp(new BN(0x3ffffff)), -1);
+ assert.equal(new BN(0x3fffffe).cmp(new BN(0x3fffffd)), 1);
+ assert.equal(new BN(0x3fffffe).cmp(new BN(0x4000000)), -1);
+ assert.equal(new BN(42).cmp(new BN(-42)), 1);
+ assert.equal(new BN(-42).cmp(new BN(42)), -1);
+ assert.equal(new BN(-42).cmp(new BN(-42)), 0);
+ assert.equal(1 / new BN(-42).cmp(new BN(-42)), Infinity);
+ });
+ });
+
+ describe('comparison shorthands', function () {
+ it('.gtn greater than', function () {
+ assert.equal(new BN(3).gtn(2), true);
+ assert.equal(new BN(3).gtn(3), false);
+ assert.equal(new BN(3).gtn(4), false);
+ });
+ it('.gt greater than', function () {
+ assert.equal(new BN(3).gt(new BN(2)), true);
+ assert.equal(new BN(3).gt(new BN(3)), false);
+ assert.equal(new BN(3).gt(new BN(4)), false);
+ });
+ it('.gten greater than or equal', function () {
+ assert.equal(new BN(3).gten(3), true);
+ assert.equal(new BN(3).gten(2), true);
+ assert.equal(new BN(3).gten(4), false);
+ });
+ it('.gte greater than or equal', function () {
+ assert.equal(new BN(3).gte(new BN(3)), true);
+ assert.equal(new BN(3).gte(new BN(2)), true);
+ assert.equal(new BN(3).gte(new BN(4)), false);
+ });
+ it('.ltn less than', function () {
+ assert.equal(new BN(2).ltn(3), true);
+ assert.equal(new BN(2).ltn(2), false);
+ assert.equal(new BN(2).ltn(1), false);
+ });
+ it('.lt less than', function () {
+ assert.equal(new BN(2).lt(new BN(3)), true);
+ assert.equal(new BN(2).lt(new BN(2)), false);
+ assert.equal(new BN(2).lt(new BN(1)), false);
+ });
+ it('.lten less than or equal', function () {
+ assert.equal(new BN(3).lten(3), true);
+ assert.equal(new BN(3).lten(2), false);
+ assert.equal(new BN(3).lten(4), true);
+ });
+ it('.lte less than or equal', function () {
+ assert.equal(new BN(3).lte(new BN(3)), true);
+ assert.equal(new BN(3).lte(new BN(2)), false);
+ assert.equal(new BN(3).lte(new BN(4)), true);
+ });
+ it('.eqn equal', function () {
+ assert.equal(new BN(3).eqn(3), true);
+ assert.equal(new BN(3).eqn(2), false);
+ assert.equal(new BN(3).eqn(4), false);
+ });
+ it('.eq equal', function () {
+ assert.equal(new BN(3).eq(new BN(3)), true);
+ assert.equal(new BN(3).eq(new BN(2)), false);
+ assert.equal(new BN(3).eq(new BN(4)), false);
+ });
+ });
+
+ describe('.fromTwos', function () {
+ it('should convert from two\'s complement to negative number', function () {
+ assert.equal(new BN('00000000', 16).fromTwos(32).toNumber(), 0);
+ assert.equal(new BN('00000001', 16).fromTwos(32).toNumber(), 1);
+ assert.equal(new BN('7fffffff', 16).fromTwos(32).toNumber(), 2147483647);
+ assert.equal(new BN('80000000', 16).fromTwos(32).toNumber(), -2147483648);
+ assert.equal(new BN('f0000000', 16).fromTwos(32).toNumber(), -268435456);
+ assert.equal(new BN('f1234567', 16).fromTwos(32).toNumber(), -249346713);
+ assert.equal(new BN('ffffffff', 16).fromTwos(32).toNumber(), -1);
+ assert.equal(new BN('fffffffe', 16).fromTwos(32).toNumber(), -2);
+ assert.equal(new BN('fffffffffffffffffffffffffffffffe', 16)
+ .fromTwos(128).toNumber(), -2);
+ assert.equal(new BN('ffffffffffffffffffffffffffffffff' +
+ 'fffffffffffffffffffffffffffffffe', 16).fromTwos(256).toNumber(), -2);
+ assert.equal(new BN('ffffffffffffffffffffffffffffffff' +
+ 'ffffffffffffffffffffffffffffffff', 16).fromTwos(256).toNumber(), -1);
+ assert.equal(new BN('7fffffffffffffffffffffffffffffff' +
+ 'ffffffffffffffffffffffffffffffff', 16).fromTwos(256).toString(10),
+ new BN('5789604461865809771178549250434395392663499' +
+ '2332820282019728792003956564819967', 10).toString(10));
+ assert.equal(new BN('80000000000000000000000000000000' +
+ '00000000000000000000000000000000', 16).fromTwos(256).toString(10),
+ new BN('-578960446186580977117854925043439539266349' +
+ '92332820282019728792003956564819968', 10).toString(10));
+ });
+ });
+
+ describe('.toTwos', function () {
+ it('should convert from negative number to two\'s complement', function () {
+ assert.equal(new BN(0).toTwos(32).toString(16), '0');
+ assert.equal(new BN(1).toTwos(32).toString(16), '1');
+ assert.equal(new BN(2147483647).toTwos(32).toString(16), '7fffffff');
+ assert.equal(new BN('-2147483648', 10).toTwos(32).toString(16), '80000000');
+ assert.equal(new BN('-268435456', 10).toTwos(32).toString(16), 'f0000000');
+ assert.equal(new BN('-249346713', 10).toTwos(32).toString(16), 'f1234567');
+ assert.equal(new BN('-1', 10).toTwos(32).toString(16), 'ffffffff');
+ assert.equal(new BN('-2', 10).toTwos(32).toString(16), 'fffffffe');
+ assert.equal(new BN('-2', 10).toTwos(128).toString(16),
+ 'fffffffffffffffffffffffffffffffe');
+ assert.equal(new BN('-2', 10).toTwos(256).toString(16),
+ 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe');
+ assert.equal(new BN('-1', 10).toTwos(256).toString(16),
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
+ assert.equal(new BN('5789604461865809771178549250434395392663' +
+ '4992332820282019728792003956564819967', 10).toTwos(256).toString(16),
+ '7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
+ assert.equal(new BN('-578960446186580977117854925043439539266' +
+ '34992332820282019728792003956564819968', 10).toTwos(256).toString(16),
+ '8000000000000000000000000000000000000000000000000000000000000000');
+ });
+ });
+
+ describe('.isBN', function () {
+ it('should return true for BN', function () {
+ assert.equal(BN.isBN(new BN()), true);
+ });
+
+ it('should return false for everything else', function () {
+ assert.equal(BN.isBN(1), false);
+ assert.equal(BN.isBN([]), false);
+ assert.equal(BN.isBN({}), false);
+ });
+ });
+});
diff --git a/node_modules/bn.js/util/genCombMulTo.js b/node_modules/bn.js/util/genCombMulTo.js
new file mode 100644
index 000000000..8b456c7c6
--- /dev/null
+++ b/node_modules/bn.js/util/genCombMulTo.js
@@ -0,0 +1,65 @@
+'use strict';
+
+// NOTE: This could be potentionally used to generate loop-less multiplications
+function genCombMulTo (alen, blen) {
+ var len = alen + blen - 1;
+ var src = [
+ 'var a = self.words;',
+ 'var b = num.words;',
+ 'var o = out.words;',
+ 'var c = 0;',
+ 'var lo;',
+ 'var mid;',
+ 'var hi;'
+ ];
+ for (var i = 0; i < alen; i++) {
+ src.push('var a' + i + ' = a[' + i + '] | 0;');
+ src.push('var al' + i + ' = a' + i + ' & 0x1fff;');
+ src.push('var ah' + i + ' = a' + i + ' >>> 13;');
+ }
+ for (i = 0; i < blen; i++) {
+ src.push('var b' + i + ' = b[' + i + '] | 0;');
+ src.push('var bl' + i + ' = b' + i + ' & 0x1fff;');
+ src.push('var bh' + i + ' = b' + i + ' >>> 13;');
+ }
+ src.push('');
+ src.push('out.negative = self.negative ^ num.negative;');
+ src.push('out.length = ' + len + ';');
+
+ for (var k = 0; k < len; k++) {
+ var minJ = Math.max(0, k - alen + 1);
+ var maxJ = Math.min(k, blen - 1);
+
+ src.push('\/* k = ' + k + ' *\/');
+ src.push('var w' + k + ' = c;');
+ src.push('c = 0;');
+ for (var j = minJ; j <= maxJ; j++) {
+ i = k - j;
+
+ src.push('lo = Math.imul(al' + i + ', bl' + j + ');');
+ src.push('mid = Math.imul(al' + i + ', bh' + j + ');');
+ src.push('mid = (mid + Math.imul(ah' + i + ', bl' + j + ')) | 0;');
+ src.push('hi = Math.imul(ah' + i + ', bh' + j + ');');
+
+ src.push('w' + k + ' = (w' + k + ' + lo) | 0;');
+ src.push('w' + k + ' = (w' + k + ' + ((mid & 0x1fff) << 13)) | 0;');
+ src.push('c = (c + hi) | 0;');
+ src.push('c = (c + (mid >>> 13)) | 0;');
+ src.push('c = (c + (w' + k + ' >>> 26)) | 0;');
+ src.push('w' + k + ' &= 0x3ffffff;');
+ }
+ }
+ // Store in separate step for better memory access
+ for (k = 0; k < len; k++) {
+ src.push('o[' + k + '] = w' + k + ';');
+ }
+ src.push('if (c !== 0) {',
+ ' o[' + k + '] = c;',
+ ' out.length++;',
+ '}',
+ 'return out;');
+
+ return src.join('\n');
+}
+
+console.log(genCombMulTo(10, 10));
diff --git a/node_modules/bn.js/util/genCombMulTo10.js b/node_modules/bn.js/util/genCombMulTo10.js
new file mode 100644
index 000000000..cf2e6e803
--- /dev/null
+++ b/node_modules/bn.js/util/genCombMulTo10.js
@@ -0,0 +1,65 @@
+'use strict';
+
+function genCombMulTo (alen, blen) {
+ var len = alen + blen - 1;
+ var src = [
+ 'var a = self.words;',
+ 'var b = num.words;',
+ 'var o = out.words;',
+ 'var c = 0;',
+ 'var lo;',
+ 'var mid;',
+ 'var hi;'
+ ];
+ for (var i = 0; i < alen; i++) {
+ src.push('var a' + i + ' = a[' + i + '] | 0;');
+ src.push('var al' + i + ' = a' + i + ' & 0x1fff;');
+ src.push('var ah' + i + ' = a' + i + ' >>> 13;');
+ }
+ for (i = 0; i < blen; i++) {
+ src.push('var b' + i + ' = b[' + i + '] | 0;');
+ src.push('var bl' + i + ' = b' + i + ' & 0x1fff;');
+ src.push('var bh' + i + ' = b' + i + ' >>> 13;');
+ }
+ src.push('');
+ src.push('out.negative = self.negative ^ num.negative;');
+ src.push('out.length = ' + len + ';');
+
+ for (var k = 0; k < len; k++) {
+ var minJ = Math.max(0, k - alen + 1);
+ var maxJ = Math.min(k, blen - 1);
+
+ src.push('\/* k = ' + k + ' *\/');
+ src.push('lo = Math.imul(al' + (k - minJ) + ', bl' + minJ + ');');
+ src.push('mid = Math.imul(al' + (k - minJ) + ', bh' + minJ + ');');
+ src.push(
+ 'mid = (mid + Math.imul(ah' + (k - minJ) + ', bl' + minJ + ')) | 0;');
+ src.push('hi = Math.imul(ah' + (k - minJ) + ', bh' + minJ + ');');
+
+ for (var j = minJ + 1; j <= maxJ; j++) {
+ i = k - j;
+
+ src.push('lo = (lo + Math.imul(al' + i + ', bl' + j + ')) | 0;');
+ src.push('mid = (mid + Math.imul(al' + i + ', bh' + j + ')) | 0;');
+ src.push('mid = (mid + Math.imul(ah' + i + ', bl' + j + ')) | 0;');
+ src.push('hi = (hi + Math.imul(ah' + i + ', bh' + j + ')) | 0;');
+ }
+
+ src.push('var w' + k + ' = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;');
+ src.push('c = (((hi + (mid >>> 13)) | 0) + (w' + k + ' >>> 26)) | 0;');
+ src.push('w' + k + ' &= 0x3ffffff;');
+ }
+ // Store in separate step for better memory access
+ for (k = 0; k < len; k++) {
+ src.push('o[' + k + '] = w' + k + ';');
+ }
+ src.push('if (c !== 0) {',
+ ' o[' + k + '] = c;',
+ ' out.length++;',
+ '}',
+ 'return out;');
+
+ return src.join('\n');
+}
+
+console.log(genCombMulTo(10, 10));