UNPKG

bn-plus.js

Version:

Big number implementation in pure javascript and Maximum support to 9999999999999900

1,793 lines (1,599 loc) 87.5 kB
(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('buffer').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 if(number < 0x20000000000000){ assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) this.words = [ number & 0x3ffffff, (number / 0x4000000) & 0x3ffffff, 1 ]; this.length = 3; }else{ assert(number <= 0x2386f26fc0ff9c); // 最大9999999999999900 (unsafe) this.words = [ number & 0x3ffffff, (number / 0x4000000) & 0x3ffffff, 2 ]; 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 || this.words[2] === 0x02)) { // 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 54 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