react / wstein / node_modules / browserify / node_modules / crypto-browserify / node_modules / public-encrypt / node_modules / bn.js / 1.patch
80555 viewsFrom f26e6ec81a999b09c626e5138f04b59abb1f5025 Mon Sep 17 00:00:00 20011From: Alexey Kudinkin <[email protected]>2Date: Tue, 9 Dec 2014 04:27:17 +03003Subject: [PATCH 01/12] First scratches FFT45---6lib/bn.js | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-71 file changed, 266 insertions(+), 3 deletions(-)89diff --git a/lib/bn.js b/lib/bn.js10index 2e990f6..9b9b857 10064411--- a/lib/bn.js12+++ b/lib/bn.js13@@ -883,15 +883,270 @@ BN.prototype._bigMulTo = function _bigMulTo(num, out) {14return out.strip();15};1617+18+function Complex(r, i) {19+ this.r = r;20+ this.i = i;21+22+ //this._norm();23+}24+25+// private26+function _iaddC(rhs) {27+ this.r += rhs.r;28+ this.i += rhs.i;29+30+ //this._norm();31+32+ return this;33+}34+35+function _addC(rhs) {36+ var t = new Complex(this.r, this.i);37+ t.iadd(rhs);38+ return t;39+}40+41+function _isubC(rhs) {42+ this.r -= rhs.r;43+ this.i -= rhs.i44+45+ //this._norm();46+47+ return this;48+}49+50+function _subC(rhs) {51+ var t = new Complex(this.r, this.i);52+ t.isub(rhs);53+ return t;54+}55+56+function _iconjC() {57+ this.i *= -1;58+ return this;59+}60+61+function _imulC(rhs) {62+ var r = this.r * rhs.r - this.i * rhs.i,63+ i = this.r * rhs.i + this.i * rhs.r;64+65+ this.r = r;66+ this.i = i;67+68+ //this._norm();69+70+ return this;71+}72+73+function _mulC(rhs) {74+ var t = new Complex(this.r, this.i);75+ t.imul(rhs);76+ return t;77+}78+79+function _cloneC() {80+ return new Complex(this.r, this.i);81+}82+83+Complex.prototype.mul = _mulC;84+Complex.prototype.imul = _imulC;85+Complex.prototype.add = _addC;86+Complex.prototype.iadd = _iaddC;87+Complex.prototype.sub = _subC;88+Complex.prototype.isub = _isubC;89+Complex.prototype.iconj = _iconjC;90+Complex.prototype.clone = _cloneC;91+92+Complex.prototype._isZero = function (v) {93+ return Math.abs(v) < 1.e-12;94+}95+96+Complex.prototype._norm = function () {97+ //if (this._isZero(this.r)) this.r = 0;98+ //if (this._isZero(this.i)) this.i = 0;99+}100+101+Complex.ZERO = new Complex(0, 0);102+103+// _FFT(this.words, thisWFT, w, N, 0);104+function _FFT(ws, p, s, tws, tp, r, N) {105+ if (N === 1) {106+ tws[tp] = ws[p];107+ //console.log("p/tp/ws/tws :", p, tp, ws, tws);108+ } else {109+ var hN = N / 2 >> 0;110+111+ var rr = r.mul(r);112+113+ var s_ = 2 * s + 1;114+115+ //console.log("-- FFT -- # ", N);116+ //console.log("-- R -- ", r);117+118+ //console.log("-- RR -- # ", rr);119+120+ _FFT(ws, p, s_, tws, tp, rr, hN); // even121+ _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd122+123+ var r_ = r.clone();124+125+ for (var i = 0; i < hN; ++i) {126+ var e = tws[tp + i];127+ var o = tws[tp + i + hN].clone();128+129+ //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)130+ //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));131+132+ o.imul(r_);133+134+ tws[tp + i] = e.add(o);135+ tws[tp + i + hN] = e.sub(o);136+137+ r_.imul(r);138+139+ //console.log("tws | ", tws)140+ }141+ }142+}143+144+var π = 3.14159265359;145+146+function _guess(n, m) {147+ var N = (n < m ? n : m) | 1, odd = N & 1;148+ var i = 0;149+ for (; N; N = N / 2 >> 0) {150+ i++;151+ }152+153+ return (1 << i + odd)154+}155+156+function _iconjugate(ws, N) {157+ if (N > 1) {158+ for (var i = 0; i < N / 2; ++i) {159+ var t = ws[i];160+ ws[i] = ws[N - i - 1];161+ ws[N - i - 1] = t;162+163+ ws[i].i *= -1;164+ ws[N - i - 1].i *= -1;165+ }166+ }167+168+ return ws;169+}170+171+function _inormalize(ws, N) {172+ var carry = 0;173+ for (var i = 0; i < N / 2; ++i) {174+175+ //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)176+ // + ((ws[2 * i].r / N + .5) >> 0)177+ // + carry;178+179+ //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {180+ // console.log(1 << 13, 1 * 0x2000);181+ // console.log(Math.round(ws[2 * i + 1].r / N), ((Math.round(ws[2 * i + 1].r / N)) << 7), (Math.round(ws[2 * i + 1].r / N) * 0x2000));182+ // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");183+ //}184+185+186+ //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)187+188+ var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)189+ + Math.round(ws[2 * i].r / N)190+ + carry;191+192+ //console.log(193+ // n.toString(16),194+ // carry.toString(16),195+ // (n & 0x3ffffff).toString(16)196+ // );197+198+ ws[i] = n & 0x3ffffff;199+200+ if (n < 0x4000000) {201+ carry = 0;202+ } else {203+ carry = Math.floor(n / 0x4000000);204+ }205+ }206+207+ return ws;208+}209+210+function _iconvertToC(ws, N) {211+ var cws = new Array(N);212+ for (var i = 0; i < N / 2; i++) {213+ var w = ws[i] || 0;214+215+ cws[2 * i] = new Complex(w & 0x1fff, 0);216+ cws[2 * i + 1] = new Complex(w >>> 13, 0);217+ }218+ return cws;219+}220+221BN.prototype.mulTo = function mulTo(num, out) {222var res;223- if (this.length + num.length < 63)224- res = this._smallMulTo(num, out);225- else226+ //if (this.length + num.length < 63)227+ // res = this._smallMulTo(num, out);228+ //else229res = this._bigMulTo(num, out);230+ // res = this._bigMulToF(num, out);231return res;232};233234+BN.prototype.mulToF = function mulToF(num, out) {235+ var res;236+ //if (this.length + num.length < 63)237+ // res = this._smallMulTo(num, out);238+ //else239+ res = this._bigMulToF(num, out);240+ return res;241+};242+243+BN.prototype._bigMulToF = function _bigMulToF(num, out) {244+ out.sign = num.sign !== this.sign;245+ out.length = this.length + num.length;246+247+ var N = 2 * _guess(this.length, num.length);248+249+ var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));250+251+ //console.log("-- W -- ", w);252+253+ var thisWFT = new Array(N),254+ numWFT = new Array(N),255+ //multWFT = new Array(N),256+ multW = new Array(N);257+258+ //console.log("A, B: ", this, num);259+260+ _FFT(_iconvertToC(this.words, N), 0, 0, thisWFT, 0, w, N);261+ _FFT(_iconvertToC(num.words, N), 0, 0, numWFT, 0, w, N);262+263+ for (var i = 0; i < N; ++i) {264+ //multWFT[i] = thisWFT[i].mul(numWFT[i]);265+ thisWFT[i].imul(numWFT[i]);266+ }267+268+ //console.log("-- MULF -- ", multWFT);269+270+ //_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);271+ _FFT(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N);272+273+ //console.log(multW);274+275+ multW = _inormalize(_iconjugate(multW, N), N);276+277+ out.words = multW;278+279+ //console.log("-- MUL -- ", multW);280+281+ return out.strip();282+};283+284// Multiply `this` by `num`285BN.prototype.mul = function mul(num) {286var out = new BN(null);287@@ -899,6 +1154,14 @@ BN.prototype.mul = function mul(num) {288return this.mulTo(num, out);289};290291+// Multiply employing FFT292+BN.prototype.mulf = function mulf(num) {293+ var out = new BN(null);294+ //out.words = new Array(this.length + num.length);295+ out.words = null;296+ return this.mulToF(num, out);297+};298+299// In-place Multiplication300BN.prototype.imul = function imul(num) {301if (this.cmpn(0) === 0 || num.cmpn(0) === 0) {302303From 21f40777824dfdc61c93a009e82c25c30d0615ed Mon Sep 17 00:00:00 2001304From: Alexey Kudinkin <[email protected]>305Date: Fri, 12 Dec 2014 00:25:08 +0300306Subject: [PATCH 02/12] Continuous probing307308---309benchmarks/index.js | 78 +++++++++++310lib/bn.js | 378 ++++++++++++++++++++++++++++++++++++++++++++++++++--311test/_fft.js | 43 ++++++3123 files changed, 486 insertions(+), 13 deletions(-)313create mode 100644 test/_fft.js314315diff --git a/benchmarks/index.js b/benchmarks/index.js316index b8cb23d..64b61d9 100644317--- a/benchmarks/index.js318+++ b/benchmarks/index.js319@@ -59,6 +59,72 @@ if (/fast/i.test(process.argv[3])) {320var a1 = new bn('012345678901234567890123456789012345678901234567890', 10);321var b1 = new bn('213509123601923760129376102397651203958123402314875', 10);322323+var a1x = new bn( 'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +324+ '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +325+ '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +326+ 'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +327+ 'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +328+ 'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +329+ 'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +330+ 'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +331+ '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +332+ '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +333+ 'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +334+ 'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +335+ '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +336+ 'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +337+ 'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +338+ '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +339+ '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +340+ '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +341+ '100050a430b47bc592995606440272a4994677577a6aaa1b' +342+ 'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +343+ 'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +344+ '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +345+ 'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +346+ '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +347+ '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +348+ '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +349+ '1c64145849b3da8c2d343410df892d958db232617f9896f1' +350+ 'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +351+ 'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +352+ 'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +353+ 'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +354+ '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0', 16);355+356+var b1x = new bn( '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +357+ '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +358+ 'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +359+ 'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +360+ 'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +361+ 'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +362+ 'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +363+ '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +364+ 'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +365+ '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +366+ '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +367+ '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +368+ 'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +369+ '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +370+ 'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +371+ '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +372+ '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +373+ 'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +374+ 'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +375+ '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +376+ 'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +377+ '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +378+ 'fbedccbc786951025597522eef283e3f56b44561a0765783' +379+ '420128638c257e54b972a76e4261892d81222b3e2039c61a' +380+ 'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +381+ 'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +382+ '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +383+ 'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +384+ 'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +385+ '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +386+ 'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +387+ '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d', 16);388+389var a2 = new bignum('012345678901234567890123456789012345678901234567890', 10);390var b2 = new bignum('213509123601923760129376102397651203958123402314875', 10);391392@@ -205,6 +271,9 @@ add('mul', {393'bn.js': function() {394a1.mul(b1);395},396+ 'bn.js[FFT]': function() {397+ a1.mulf(b1);398+ }399'bignum': function() {400a2.mul(b2);401},402@@ -222,6 +291,15 @@ add('mul', {403}404});405406+add('mul-jumbo', {407+ 'bn.js': function() {408+ a1x.mul(b1x);409+ },410+ 'bn.js[FFT]': function() {411+ a1x.mulf(b1x);412+ }413+});414+415add('sqr', {416'bn.js': function() {417a1.mul(a1);418diff --git a/lib/bn.js b/lib/bn.js419index 9b9b857..c803573 100644420--- a/lib/bn.js421+++ b/lib/bn.js422@@ -958,16 +958,14 @@ Complex.prototype.isub = _isubC;423Complex.prototype.iconj = _iconjC;424Complex.prototype.clone = _cloneC;425426-Complex.prototype._isZero = function (v) {427- return Math.abs(v) < 1.e-12;428-}429+//Complex.prototype._isZero = function (v) {430+// return Math.abs(v) < 1.e-12;431+//}432433-Complex.prototype._norm = function () {434+//Complex.prototype._norm = function () {435//if (this._isZero(this.r)) this.r = 0;436//if (this._isZero(this.i)) this.i = 0;437-}438-439-Complex.ZERO = new Complex(0, 0);440+//}441442// _FFT(this.words, thisWFT, w, N, 0);443function _FFT(ws, p, s, tws, tp, r, N) {444@@ -1003,6 +1001,11 @@ function _FFT(ws, p, s, tws, tp, r, N) {445tws[tp + i] = e.add(o);446tws[tp + i + hN] = e.sub(o);447448+ //console.log(tws);449+450+ assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))451+ assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))452+453r_.imul(r);454455//console.log("tws | ", tws)456@@ -1010,6 +1013,63 @@ function _FFT(ws, p, s, tws, tp, r, N) {457}458}459460+461+function _FFTL(ws, p, s, tws, tp, r, N) {462+ //if (N === 1) {463+ // tws[tp] = ws[p];464+ // //console.log("p/tp/ws/tws :", p, tp, ws, tws);465+ //} else {466+ // var hN = N / 2 >> 0;467+ //468+ // var rr = r.mul(r);469+ //470+ // var s_ = 2 * s + 1;471+ //472+ // //console.log("-- FFT -- # ", N);473+ // //console.log("-- R -- ", r);474+ //475+ // //console.log("-- RR -- # ", rr);476+ //477+ // _FFT(ws, p, s_, tws, tp, rr, hN); // even478+ // _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd479+ //480+ // var r_ = r.clone();481+ //482+ // for (var i = 0; i < hN; ++i) {483+ // var e = tws[tp + i];484+ // var o = tws[tp + i + hN].clone();485+ //486+ // //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)487+ // //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));488+ //489+ // o.imul(r_);490+ //491+ // tws[tp + i] = e.add(o);492+ // tws[tp + i + hN] = e.sub(o);493+ //494+ // r_.imul(r);495+ //496+ // //console.log("tws | ", tws)497+ // }498+ //}499+500+ var hN = N / 2 >> 0;501+502+ for (var i = 0; i < hN; i++) {503+ tws[2 * i] = ws[i];504+ tws[2 * i + 1] = ws[i + hN];505+ }506+507+ var p = 0;508+509+ for (var l = 1; l < N + 1; l << 1, p = 0) {510+ for (var j = p; j < p + l; ++j, p += l) {511+ var e = tws[j];512+ var o = tws[j + l].clone();513+ }514+ }515+}516+517var π = 3.14159265359;518519function _guess(n, m) {520@@ -1037,7 +1097,7 @@ function _iconjugate(ws, N) {521return ws;522}523524-function _inormalize(ws, N) {525+function _inormalize13(ws, N) {526var carry = 0;527for (var i = 0; i < N / 2; ++i) {528529@@ -1051,8 +1111,11 @@ function _inormalize(ws, N) {530// assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");531//}532533-534//assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)535+ //536+ //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)537+ // + Math.round(ws[2 * i].r / N)538+ // + carry;539540var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)541+ Math.round(ws[2 * i].r / N)542@@ -1076,7 +1139,170 @@ function _inormalize(ws, N) {543return ws;544}545546-function _iconvertToC(ws, N) {547+function _inormalize20(ws, N) {548+549+ var carry = 0;550+ var seek = 0;551+552+ for (var j = 0; j < N; ++j) {553+ ws[j] = Math.round(ws[j].r / N);554+ }555+556+ for (var i = 0; i < N; ++i) {557+ //var w = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)558+ // + ((ws[2 * i].r / N + .5) >> 0)559+ // + carry;560+561+ //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {562+ // console.log(1 << 13, 1 * 0x2000);563+ // console.log(Math.round(ws[2 * i + 1].r / N), ((Math.round(ws[2 * i + 1].r / N)) << 7), (Math.round(ws[2 * i + 1].r / N) * 0x2000));564+ // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");565+ //}566+567+ //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)568+569+ //var w = ws[i];570+ //571+ //assert(w < (0x4000000 * 0x4000000))572+ //573+ //console.log("Before ", w, w & 0x3ffffff, carry);574+ //575+ //if (i + 1 < N) {576+ // w += ((ws[i + 1] + 0.5) & 0x3ffffff) * 0x100000;577+ //578+ // ws[i + 1] &= 0x4000000;579+ //}580+ //581+ //w += carry;582+ //583+ //ws[i] = w & 0x3ffffff;584+ //585+ //carry = Math.floor(w / 0x4000000);586+ //587+ //console.log("After ", w, w & 0x3ffffff, carry);588+589+ var w = ws[i];590+591+ //console.log(w, carry, (w & 0x3ffffff));592+593+ var j = i;594+595+ //if (w < 0x4000000)596+ {597+ var pseek = seek;598+ seek += 26 - 20;599+600+ if (seek > 20) {601+ if (i < N - 1) {602+ w += ws[i + 1] * 0x100000 / (1 << pseek)603+604+ // !!!605+ ++i;606+607+ seek -= 20;608+609+ var d = 1 << seek;610+611+ w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);612+ ws[i + 1] /= d;613+ }614+ }615+ else616+ {617+ var pd = 1 << (pseek);618+ var d = 1 << (seek);619+620+ //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)621+622+ w += (ws[i + 1] & (d - 1)) * 0x100000 / pd;623+ ws[i + 1] /= d;624+ }625+ }626+627+ //console.log(w, w & 0x3ffffff, carry)628+629+ assert(w < 0x4000000 * 0x4000000)630+ assert(carry < 0x4000000 * 0x4000000)631+632+ w += carry;633+634+ //console.log(w, w & 0x3ffffff, carry)635+636+ ws[j] = w & 0x3ffffff;637+638+ carry = Math.floor(w / 0x4000000);639+ }640+641+ return ws;642+}643+644+function _inormalize18(ws, N) {645+646+ var carry = 0;647+ var seek = 0;648+649+ for (var j = 0; j < N; ++j) {650+ ws[j] = Math.round(ws[j].r / N);651+ }652+653+ for (var i = 0; i < N; ++i) {654+ var w = ws[i];655+656+ //console.log(w, carry, (w & 0x3ffffff));657+658+ var j = i;659+660+ //if (w < 0x4000000)661+ {662+ var pseek = seek;663+ seek += 26 - 18;664+665+ if (seek > 18) {666+ if (i < N - 1) {667+ w += ws[i + 1] * 0x40000 / (1 << pseek)668+669+ // !!!670+ ++i;671+672+ seek -= 18;673+674+ var d = 1 << seek;675+676+ w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);677+ ws[i + 1] /= d;678+ }679+ }680+ else681+ {682+ var pd = 1 << (pseek);683+ var d = 1 << (seek);684+685+ //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)686+687+ w += (ws[i + 1] & (d - 1)) * 0x40000 / pd;688+ ws[i + 1] /= d;689+ }690+ }691+692+ //console.log(w, w & 0x3ffffff, carry)693+694+ assert(w < 0x4000000 * 0x4000000)695+ assert(carry < 0x4000000 * 0x4000000)696+697+ w += carry;698+699+ //console.log(w, w & 0x3ffffff, carry)700+701+ ws[j] = w & 0x3ffffff;702+703+ carry = Math.floor(w / 0x4000000);704+ }705+706+ return ws;707+}708+709+710+function _iconvertToC13(ws, N) {711var cws = new Array(N);712for (var i = 0; i < N / 2; i++) {713var w = ws[i] || 0;714@@ -1087,6 +1313,125 @@ function _iconvertToC(ws, N) {715return cws;716}717718+function _iconvertToC20(ws, N) {719+ var cws = new Array(N);720+721+ for (var i = 0, j = 0, seek = 20; i < N; ++i) {722+ var w = ws[i] || 0;723+ var l = 26;724+725+ while (l > 0) {726+ cws[j] = cws[j] || 0;727+728+ if (seek >= l) {729+ cws[j] += w << (20 - seek);730+731+ seek -= l;732+ if (seek === 0) seek = 20;733+ l = 0;734+ } else {735+ cws[j] += (w & ((1 << seek) - 1)) << (20 - seek);736+ w /= 1 << seek;737+738+ ++j;739+ l -= seek;740+ seek = 20;741+ }742+ }743+ }744+745+ for (i = 0; i < N; ++i) {746+ cws[i] = new Complex(cws[i], 0);747+ }748+749+ return cws;750+}751+752+function _iconvertToC18(ws, N) {753+ var cws = new Array(N);754+755+ for (var i = 0, j = 0, seek = 18; i < N; ++i) {756+ var w = ws[i] || 0;757+ var l = 26;758+759+ while (l > 0) {760+ cws[j] = cws[j] || 0;761+762+ if (seek >= l) {763+ cws[j] += w << (18 - seek);764+765+ seek -= l;766+ if (seek === 0) seek = 18;767+ l = 0;768+ } else {769+ cws[j] += (w & ((1 << seek) - 1)) << (18 - seek);770+ w /= 1 << seek;771+772+ ++j;773+ l -= seek;774+ seek = 18;775+ }776+ }777+ }778+779+ for (i = 0; i < N; ++i) {780+ cws[i] = new Complex(cws[i], 0);781+ }782+783+ return cws;784+}785+786+function _iconvertTo13(ws, N) {787+ var cws = new Array(N);788+ var carry = 0;789+790+ var i = 0;791+ for (i = 0; i < N; ++i) {792+ ws[i] = Math.round(ws[i].r / N);793+ }794+795+ i = 0;796+ for (var j = 0; true; ++j) {797+798+ if (carry < 0x2000) {799+ if (i === N)800+ break;801+802+ carry += ws[i];803+ i++;804+ }805+806+ var lo = carry & 0x1fff; // Here we don't care about overflow, since807+ // since overflow may only "screw" (trim) high-order808+ // bits, while we're particularly interested in low-order ones809+810+ //console.log(carry, lo)811+812+ carry = carry / 0x2000; // Since shift would trigger conversion from813+ // float (64) to int (32)814+815+ cws[j] = lo;816+ }817+818+ //for (var i = 0; i < N; i++) {819+ // carry += Math.round(ws[i].r / N);820+ //821+ //822+ // var lo = carry & 0x1fff; // Here we don't care about overflow, since823+ // // since overflow may only "screw" (trim) high-order824+ // // bits, while we're particularly interested in low-order ones825+ //826+ // console.log(carry, lo)827+ //828+ // carry = carry / 0x2000; // Since shift would trigger conversion from829+ // // float (64) to int (32)830+ //831+ // cws[i] = lo;832+ //}833+834+ return cws;835+}836+837BN.prototype.mulTo = function mulTo(num, out) {838var res;839//if (this.length + num.length < 63)840@@ -1111,6 +1456,7 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {841out.length = this.length + num.length;842843var N = 2 * _guess(this.length, num.length);844+ //var N = _guess(this.length * 1.3, num.length * 1.3);845846var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));847848@@ -1123,8 +1469,12 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {849850//console.log("A, B: ", this, num);851852- _FFT(_iconvertToC(this.words, N), 0, 0, thisWFT, 0, w, N);853- _FFT(_iconvertToC(num.words, N), 0, 0, numWFT, 0, w, N);854+ _FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);855+ _FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);856+ //_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);857+ //_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);858+ //_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);859+ //_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);860861for (var i = 0; i < N; ++i) {862//multWFT[i] = thisWFT[i].mul(numWFT[i]);863@@ -1138,7 +1488,9 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {864865//console.log(multW);866867- multW = _inormalize(_iconjugate(multW, N), N);868+ multW = _inormalize13(_iconjugate(multW, N), N);869+ //multW = _inormalize20(_iconjugate(multW, N), N);870+ //multW = _inormalize18(_iconjugate(multW, N), N);871872out.words = multW;873874diff --git a/test/_fft.js b/test/_fft.js875new file mode 100644876index 0000000..78c5233877--- /dev/null878+++ b/test/_fft.js879@@ -0,0 +1,43 @@880+var BN = require("../lib/bn.js").BN881+var fixtures = require("./fixtures.js")882+883+//var a = new BN("1");884+//var b = new BN("1");885+886+//var a = new BN("123");887+//var b = new BN("123");888+889+//var a = new BN("123456");890+//var b = new BN("123456");891+892+//var a = new BN("12345690");893+//var b = new BN("1234560");894+895+//var a = new BN("123456900");896+//var b = new BN("12345601");897+898+//var a = new BN("123456789");899+//var b = new BN("123456780");900+901+//var a = new BN("123456789");902+//var b = new BN("123456789");903+904+//var a = new BN(905+// '13f29a3e0bc10e100ce0', 16);906+//var b = a.clone();907+908+909+var a = new BN(fixtures.dhGroups.p17.q, 16);910+var b = a.clone();911+var qs = fixtures.dhGroups.p17.qs;912+913+var c = a.mulf(b);914+var c_ = a.mul(b);915+916+//console.log(c.words);917+console.log(c);918+console.log("------")919+//console.log(c_.words);920+console.log(c_);921+922+//assert(c === new BN(2))923924From 47297ab0ccfc9e66b37dd53a86b7fcb09c17db63 Mon Sep 17 00:00:00 2001925From: Alexey Kudinkin <[email protected]>926Date: Sun, 14 Dec 2014 19:51:28 +0300927Subject: [PATCH 03/12] Unrolled recursion928929---930lib/bn.js | 141 +++++++++++++++++++++++++++++++++++------------------------931test/_fft.js | 10 ++++-9322 files changed, 93 insertions(+), 58 deletions(-)933934diff --git a/lib/bn.js b/lib/bn.js935index c803573..d173a6d 100644936--- a/lib/bn.js937+++ b/lib/bn.js938@@ -1003,8 +1003,8 @@ function _FFT(ws, p, s, tws, tp, r, N) {939940//console.log(tws);941942- assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))943- assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))944+ //assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))945+ //assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))946947r_.imul(r);948949@@ -1013,73 +1013,98 @@ function _FFT(ws, p, s, tws, tp, r, N) {950}951}952953+var π = 3.14159265359;954955-function _FFTL(ws, p, s, tws, tp, r, N) {956- //if (N === 1) {957- // tws[tp] = ws[p];958- // //console.log("p/tp/ws/tws :", p, tp, ws, tws);959- //} else {960- // var hN = N / 2 >> 0;961- //962- // var rr = r.mul(r);963- //964- // var s_ = 2 * s + 1;965- //966- // //console.log("-- FFT -- # ", N);967- // //console.log("-- R -- ", r);968- //969- // //console.log("-- RR -- # ", rr);970- //971- // _FFT(ws, p, s_, tws, tp, rr, hN); // even972- // _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd973- //974- // var r_ = r.clone();975- //976- // for (var i = 0; i < hN; ++i) {977- // var e = tws[tp + i];978- // var o = tws[tp + i + hN].clone();979- //980- // //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)981- // //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));982- //983- // o.imul(r_);984- //985- // tws[tp + i] = e.add(o);986- // tws[tp + i + hN] = e.sub(o);987- //988- // r_.imul(r);989- //990- // //console.log("tws | ", tws)991- // }992+993+function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {994+ //var hN = N / 2 >> 0;995+996+ //for (var j = 0; j < 2; ++j)997+ //for (var i = 0, hhN = hN >> 1, dN = hN; i < hhN; ++i, dN >>= 1) {998+ // tws[2 * i] = ws[dN + j];999+ // tws[2 * i + 1] = ws[dN + j + ];1000//}10011002- var hN = N / 2 >> 0;1003+ //console.log("XXXXX")1004+ //console.log("WS, TWS", ws, tws)10051006- for (var i = 0; i < hN; i++) {1007- tws[2 * i] = ws[i];1008- tws[2 * i + 1] = ws[i + hN];1009- }1010+ _permuteTo(rbt, ws, tws, N);1011+1012+ var hN = N >>> 1;1013+1014+ for (var s = 1; s < N; s <<= 1) {1015+ var l = s << 1;1016+ var r = new Complex(Math.cos(2 * π / l), Math.sin(2 * π / l));1017+1018+ for (var p = 0; p < N; p += l) {1019+ var r_ = r.clone();1020+1021+ for (var j = 0; j < s; ++j) {1022+ var e = tws[p + j];1023+ var o = tws[p + j + s].clone();1024+1025+ o.imul(r_);10261027- var p = 0;1028+ tws[p + j] = e.add(o);1029+ tws[p + j + s] = e.sub(o)10301031- for (var l = 1; l < N + 1; l << 1, p = 0) {1032- for (var j = p; j < p + l; ++j, p += l) {1033- var e = tws[j];1034- var o = tws[j + l].clone();1035+ //assert(tws[p + j].r < (0x4000000 * 0x4000000 * 2))1036+ //assert(tws[p + j + s].r < (0x4000000 * 0x4000000 * 2))1037+1038+ if (j !== l) r_.imul(r);1039+ }1040}1041+1042+ //console.log(tws)1043}1044}10451046-var π = 3.14159265359;1047+function _makeRBT(N) {1048+ var t = new Array(N);1049+ var l = (Math.log(N) / Math.log(2)) >> 0;1050+ for (var i = 0; i < N; ++i) {1051+ t[i] = _revbin(i, l, N);1052+ }1053+1054+ return t;1055+}1056+1057+function _permuteTo(rbt, ws, tws, N) {1058+ //var l = (Math.log(N) / Math.log(2)) >> 0;1059+ for (var i = 0; i < N; ++i) {1060+ //var r = _revbin(i, l, N);1061+ //console.log("REVBIN: ", i, r)1062+ //if (r > i) {1063+ // var t = ws[i];1064+ // ws[i] = ws[r];1065+ // ws[r] = t;1066+ //}1067+ tws[i] = ws[rbt[i]];1068+ }1069+}1070+1071+function _revbin(x, l, N) {1072+ if (x === 0 || x === N - 1)1073+ return x;1074+1075+ var rb = 0;1076+ for (var i = 0; i < l; ++i) {1077+ rb |= (x & 1) << (l - i - 1);1078+ x >>= 1;1079+ }1080+1081+ return rb;1082+}1083+10841085function _guess(n, m) {1086- var N = (n < m ? n : m) | 1, odd = N & 1;1087+ var N = Math.max(m, n) | 1, odd = N & 1;1088var i = 0;1089- for (; N; N = N / 2 >> 0) {1090+ while (N = N / 2 >> 0) {1091i++;1092}10931094- return (1 << i + odd)1095+ return (1 << i + 1 + odd)1096}10971098function _iconjugate(ws, N) {1099@@ -1469,8 +1494,12 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {11001101//console.log("A, B: ", this, num);11021103- _FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);1104- _FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);1105+ var rbt = _makeRBT(N);1106+1107+ //_FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);1108+ //_FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);1109+ _FFTL(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N, rbt);1110+ _FFTL(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N, rbt);1111//_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);1112//_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);1113//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);1114@@ -1484,7 +1513,7 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1115//console.log("-- MULF -- ", multWFT);11161117//_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);1118- _FFT(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N);1119+ _FFTL(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N, rbt);11201121//console.log(multW);11221123diff --git a/test/_fft.js b/test/_fft.js1124index 78c5233..40237ed 1006441125--- a/test/_fft.js1126+++ b/test/_fft.js1127@@ -4,9 +4,15 @@ var fixtures = require("./fixtures.js")1128//var a = new BN("1");1129//var b = new BN("1");11301131+//var a = new BN("2");1132+//var b = new BN("13");1133+1134//var a = new BN("123");1135//var b = new BN("123");11361137+//var a = new BN("12345");1138+//var b = new BN("1");1139+1140//var a = new BN("123456");1141//var b = new BN("123456");11421143@@ -16,8 +22,8 @@ var fixtures = require("./fixtures.js")1144//var a = new BN("123456900");1145//var b = new BN("12345601");11461147-//var a = new BN("123456789");1148-//var b = new BN("123456780");1149+//var a = new BN("0x2000", 16);1150+//var b = new BN("12345678");11511152//var a = new BN("123456789");1153//var b = new BN("123456789");11541155From c5570b41d7b8b4b72439ea4a5e1100b715b55d2e Mon Sep 17 00:00:00 20011156From: Alexey Kudinkin <[email protected]>1157Date: Sun, 14 Dec 2014 21:04:28 +03001158Subject: [PATCH 04/12] Remastered FFT to purge any object creation (except1159arrays)11601161---1162lib/bn.js | 299 ++++++++++++++++++++++++++++++++++++++++++++++----------------11631 file changed, 221 insertions(+), 78 deletions(-)11641165diff --git a/lib/bn.js b/lib/bn.js1166index d173a6d..460a3bd 1006441167--- a/lib/bn.js1168+++ b/lib/bn.js1169@@ -1016,7 +1016,7 @@ function _FFT(ws, p, s, tws, tp, r, N) {1170var π = 3.14159265359;117111721173-function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {1174+function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {1175//var hN = N / 2 >> 0;11761177//for (var j = 0; j < 2; ++j)1178@@ -1028,30 +1028,57 @@ function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {1179//console.log("XXXXX")1180//console.log("WS, TWS", ws, tws)11811182- _permuteTo(rbt, ws, tws, N);1183-1184- var hN = N >>> 1;1185+ _permuteTo(rbt, rws, iws, rtws, itws, N);11861187for (var s = 1; s < N; s <<= 1) {1188var l = s << 1;1189- var r = new Complex(Math.cos(2 * π / l), Math.sin(2 * π / l));1190+1191+ var rtwdf = Math.cos(2 * π / l);1192+ var itwdf = Math.sin(2 * π / l);11931194for (var p = 0; p < N; p += l) {1195- var r_ = r.clone();1196+ var rtwdf_ = rtwdf;1197+ var itwdf_ = itwdf;11981199for (var j = 0; j < s; ++j) {1200- var e = tws[p + j];1201- var o = tws[p + j + s].clone();12021203- o.imul(r_);1204+ //var e = tws[p + j];1205+1206+ var re = rtws[p + j];1207+ var ie = itws[p + j];1208+1209+ //var o = tws[p + j + s].clone();1210+1211+ var ro = rtws[p + j + s];1212+ var io = itws[p + j + s];1213+1214+ //o.imul(r_);1215+1216+ var rx = rtwdf_ * ro - itwdf_ * io;1217+1218+ io = rtwdf_ * io + itwdf_ * ro;1219+ ro = rx;12201221- tws[p + j] = e.add(o);1222- tws[p + j + s] = e.sub(o)1223+ //tws[p + j] = e.add(o);1224+1225+ rtws[p + j] = re + ro;1226+ itws[p + j] = ie + io;1227+1228+ //tws[p + j + s] = e.sub(o)1229+1230+ rtws[p + j + s] = re - ro;1231+ itws[p + j + s] = ie - io;12321233//assert(tws[p + j].r < (0x4000000 * 0x4000000 * 2))1234//assert(tws[p + j + s].r < (0x4000000 * 0x4000000 * 2))12351236- if (j !== l) r_.imul(r);1237+ if (j !== l) {1238+ //r_.imul(r);1239+ var rx = rtwdf * rtwdf_ - itwdf * itwdf_;1240+1241+ itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;1242+ rtwdf_ = rx;1243+ }1244}1245}12461247@@ -1060,7 +1087,7 @@ function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {1248}12491250function _makeRBT(N) {1251- var t = new Array(N);1252+ var t = new Int32Array(N);1253var l = (Math.log(N) / Math.log(2)) >> 0;1254for (var i = 0; i < N; ++i) {1255t[i] = _revbin(i, l, N);1256@@ -1069,7 +1096,7 @@ function _makeRBT(N) {1257return t;1258}12591260-function _permuteTo(rbt, ws, tws, N) {1261+function _permuteTo(rbt, rws, iws, rtws, itws, N) {1262//var l = (Math.log(N) / Math.log(2)) >> 0;1263for (var i = 0; i < N; ++i) {1264//var r = _revbin(i, l, N);1265@@ -1079,7 +1106,8 @@ function _permuteTo(rbt, ws, tws, N) {1266// ws[i] = ws[r];1267// ws[r] = t;1268//}1269- tws[i] = ws[rbt[i]];1270+ rtws[i] = rws[rbt[i]];1271+ itws[i] = iws[rbt[i]];1272}1273}12741275@@ -1122,6 +1150,22 @@ function _iconjugate(ws, N) {1276return ws;1277}12781279+function _iconjugateX(rws, iws, N) {1280+ if (N > 1) {1281+ for (var i = 0; i < N / 2; ++i) {1282+ var t = rws[i];1283+1284+ rws[i] = rws[N - i - 1];1285+ rws[N - i - 1] = t;1286+1287+ t = iws[i];1288+1289+ iws[i] = -iws[N - i - 1];1290+ iws[N - i - 1] = -t;1291+ }1292+ }1293+}1294+1295function _inormalize13(ws, N) {1296var carry = 0;1297for (var i = 0; i < N / 2; ++i) {1298@@ -1164,6 +1208,49 @@ function _inormalize13(ws, N) {1299return ws;1300}13011302+1303+function _inormalize13X(ws, N) {1304+ var carry = 0;1305+ for (var i = 0; i < N / 2; ++i) {1306+1307+ //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)1308+ // + ((ws[2 * i].r / N + .5) >> 0)1309+ // + carry;1310+1311+ //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {1312+ // console.log(1 << 13, 1 * 0x2000);1313+ // console.log(Math.round(ws[2 * i + 1].r / N), ((Math.round(ws[2 * i + 1].r / N)) << 7), (Math.round(ws[2 * i + 1].r / N) * 0x2000));1314+ // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");1315+ //}1316+1317+ //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)1318+ //1319+ //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)1320+ // + Math.round(ws[2 * i].r / N)1321+ // + carry;1322+1323+ var n = (Math.round(ws[2 * i + 1] / N) * 0x2000)1324+ + Math.round(ws[2 * i] / N)1325+ + carry;1326+1327+ //console.log(1328+ // n.toString(16),1329+ // carry.toString(16),1330+ // (n & 0x3ffffff).toString(16)1331+ // );1332+1333+ ws[i] = n & 0x3ffffff;1334+1335+ if (n < 0x4000000) {1336+ carry = 0;1337+ } else {1338+ carry = Math.floor(n / 0x4000000);1339+ }1340+ }1341+1342+ return ws;1343+}1344+1345function _inormalize20(ws, N) {13461347var carry = 0;1348@@ -1338,6 +1425,18 @@ function _iconvertToC13(ws, N) {1349return cws;1350}13511352+function _iconvertTo13(ws, rws, iws, N) {1353+ for (var i = 0; i < N / 2; i++) {1354+ var w = ws[i] | 0;1355+1356+ rws[2 * i] = w & 0x1fff;1357+ iws[2 * i] = 0;1358+1359+ rws[2 * i + 1] = w >>> 13;1360+ iws[2 * i + 1] = 0;1361+ }1362+}1363+1364function _iconvertToC20(ws, N) {1365var cws = new Array(N);13661367@@ -1406,56 +1505,56 @@ function _iconvertToC18(ws, N) {1368return cws;1369}13701371-function _iconvertTo13(ws, N) {1372- var cws = new Array(N);1373- var carry = 0;1374-1375- var i = 0;1376- for (i = 0; i < N; ++i) {1377- ws[i] = Math.round(ws[i].r / N);1378- }1379-1380- i = 0;1381- for (var j = 0; true; ++j) {1382-1383- if (carry < 0x2000) {1384- if (i === N)1385- break;1386-1387- carry += ws[i];1388- i++;1389- }1390-1391- var lo = carry & 0x1fff; // Here we don't care about overflow, since1392- // since overflow may only "screw" (trim) high-order1393- // bits, while we're particularly interested in low-order ones1394-1395- //console.log(carry, lo)1396-1397- carry = carry / 0x2000; // Since shift would trigger conversion from1398- // float (64) to int (32)1399-1400- cws[j] = lo;1401- }1402-1403- //for (var i = 0; i < N; i++) {1404- // carry += Math.round(ws[i].r / N);1405- //1406- //1407- // var lo = carry & 0x1fff; // Here we don't care about overflow, since1408- // // since overflow may only "screw" (trim) high-order1409- // // bits, while we're particularly interested in low-order ones1410- //1411- // console.log(carry, lo)1412- //1413- // carry = carry / 0x2000; // Since shift would trigger conversion from1414- // // float (64) to int (32)1415- //1416- // cws[i] = lo;1417- //}1418-1419- return cws;1420-}1421+//function _iconvertTo13(ws, N) {1422+// var cws = new Array(N);1423+// var carry = 0;1424+//1425+// var i = 0;1426+// for (i = 0; i < N; ++i) {1427+// ws[i] = Math.round(ws[i].r / N);1428+// }1429+//1430+// i = 0;1431+// for (var j = 0; true; ++j) {1432+//1433+// if (carry < 0x2000) {1434+// if (i === N)1435+// break;1436+//1437+// carry += ws[i];1438+// i++;1439+// }1440+//1441+// var lo = carry & 0x1fff; // Here we don't care about overflow, since1442+// // since overflow may only "screw" (trim) high-order1443+// // bits, while we're particularly interested in low-order ones1444+//1445+// //console.log(carry, lo)1446+//1447+// carry = carry / 0x2000; // Since shift would trigger conversion from1448+// // float (64) to int (32)1449+//1450+// cws[j] = lo;1451+// }1452+//1453+// //for (var i = 0; i < N; i++) {1454+// // carry += Math.round(ws[i].r / N);1455+// //1456+// //1457+// // var lo = carry & 0x1fff; // Here we don't care about overflow, since1458+// // // since overflow may only "screw" (trim) high-order1459+// // // bits, while we're particularly interested in low-order ones1460+// //1461+// // console.log(carry, lo)1462+// //1463+// // carry = carry / 0x2000; // Since shift would trigger conversion from1464+// // // float (64) to int (32)1465+// //1466+// // cws[i] = lo;1467+// //}1468+//1469+// return cws;1470+//}14711472BN.prototype.mulTo = function mulTo(num, out) {1473var res;1474@@ -1483,14 +1582,14 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1475var N = 2 * _guess(this.length, num.length);1476//var N = _guess(this.length * 1.3, num.length * 1.3);14771478- var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));1479+ //var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));14801481//console.log("-- W -- ", w);14821483- var thisWFT = new Array(N),1484- numWFT = new Array(N),1485- //multWFT = new Array(N),1486- multW = new Array(N);1487+ //var thisWFT = new Array(N),1488+ // numWFT = new Array(N),1489+ // //multWFT = new Array(N),1490+ // multW = new Array(N);14911492//console.log("A, B: ", this, num);14931494@@ -1498,36 +1597,80 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {14951496//_FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);1497//_FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);1498- _FFTL(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N, rbt);1499- _FFTL(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N, rbt);1500//_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);1501//_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);1502//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);1503//_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);15041505+ var rThisWs = new Array(N),1506+ iThisWs = new Array(N),1507+ rThisWsT = new Array(N), // T for Transformed1508+ iThisWsT = new Array(N),1509+1510+ rNumWs = new Array(N),1511+ iNumWs = new Array(N),1512+ rNumWsT = new Array(N),1513+ iNumWsT = new Array(N),1514+1515+ rMultWs = new Array(N),1516+ iMultWs = new Array(N);1517+1518+ _iconvertTo13(this.words, rThisWs, iThisWs, N);1519+ _iconvertTo13(num.words, rNumWs, iNumWs, N);1520+1521+ _FFTL(rThisWs, iThisWs, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);1522+1523+ //console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))1524+ //console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))1525+1526+ _FFTL(rNumWs, iNumWs, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);1527+1528+ //console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))1529+ //console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))1530+1531for (var i = 0; i < N; ++i) {1532- //multWFT[i] = thisWFT[i].mul(numWFT[i]);1533- thisWFT[i].imul(numWFT[i]);1534+ //thisWFT[i].imul(numWFT[i]);1535+ var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];1536+1537+ iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]1538+ rThisWsT[i] = rx;1539}15401541+ //console.log("X * Y[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))1542+1543//console.log("-- MULF -- ", multWFT);15441545//_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);1546- _FFTL(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N, rbt);15471548- //console.log(multW);1549+ _iconjugateX(rThisWsT, iThisWsT, N);1550+1551+ //console.log("X * Y[R/I] Transformed Conjugated", _toArray(rThisWsT), _toArray(iThisWsT))1552+1553+ _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, iMultWs, 0, 0, N, rbt);1554+1555+ //console.log("X * Y[R/I] Inverse FFT", _toArray(rMultWs), _toArray(iMultWs))1556+1557+ _iconjugateX(rMultWs, iMultWs, N);1558+1559+ _inormalize13X(rMultWs, N);1560+1561+ //console.log("X * Y[R/I] Conjugated Normalized", _toArray(rMultWs), _toArray(iMultWs))15621563- multW = _inormalize13(_iconjugate(multW, N), N);1564//multW = _inormalize20(_iconjugate(multW, N), N);1565//multW = _inormalize18(_iconjugate(multW, N), N);15661567- out.words = multW;1568+ out.words = _toArray(rMultWs);15691570//console.log("-- MUL -- ", multW);15711572return out.strip();1573};15741575+function _toArray(f64a) {1576+ return [].slice.call(f64a);1577+}1578+1579+1580// Multiply `this` by `num`1581BN.prototype.mul = function mul(num) {1582var out = new BN(null);15831584From 6dde038bb6100b4aa972c1ab22825dfefbfa1a3e Mon Sep 17 00:00:00 20011585From: Alexey Kudinkin <[email protected]>1586Date: Sun, 14 Dec 2014 22:23:59 +03001587Subject: [PATCH 05/12] Vanished some more absurd15881589---1590lib/bn.js | 39 +++++++++++++++++----------------------15911 file changed, 17 insertions(+), 22 deletions(-)15921593diff --git a/lib/bn.js b/lib/bn.js1594index 460a3bd..36beb6d 1006441595--- a/lib/bn.js1596+++ b/lib/bn.js1597@@ -1087,7 +1087,7 @@ function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {1598}15991600function _makeRBT(N) {1601- var t = new Int32Array(N);1602+ var t = new Array(N);1603var l = (Math.log(N) / Math.log(2)) >> 0;1604for (var i = 0; i < N; ++i) {1605t[i] = _revbin(i, l, N);1606@@ -1125,7 +1125,7 @@ function _revbin(x, l, N) {1607}160816091610-function _guess(n, m) {1611+function _guess13(n, m) {1612var N = Math.max(m, n) | 1, odd = N & 1;1613var i = 0;1614while (N = N / 2 >> 0) {1615@@ -1425,15 +1425,12 @@ function _iconvertToC13(ws, N) {1616return cws;1617}16181619-function _iconvertTo13(ws, rws, iws, N) {1620+function _iconvertTo13(ws, rws, N) {1621for (var i = 0; i < N / 2; i++) {1622var w = ws[i] | 0;16231624- rws[2 * i] = w & 0x1fff;1625- iws[2 * i] = 0;1626-1627- rws[2 * i + 1] = w >>> 13;1628- iws[2 * i + 1] = 0;1629+ rws[2 * i] = w & 0x1fff;1630+ rws[2 * i + 1] = w >>> 13;1631}1632}16331634@@ -1579,8 +1576,8 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1635out.sign = num.sign !== this.sign;1636out.length = this.length + num.length;16371638- var N = 2 * _guess(this.length, num.length);1639- //var N = _guess(this.length * 1.3, num.length * 1.3);1640+ var N = 2 * _guess13(this.length, num.length);1641+ //var N = _guess13(this.length * 1.3, num.length * 1.3);16421643//var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));16441645@@ -1602,28 +1599,30 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1646//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);1647//_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);16481649- var rThisWs = new Array(N),1650- iThisWs = new Array(N),1651+ var zeroes = new Array(N),1652+ rThisWs = new Array(N),1653rThisWsT = new Array(N), // T for Transformed1654iThisWsT = new Array(N),16551656rNumWs = new Array(N),1657- iNumWs = new Array(N),1658rNumWsT = new Array(N),1659iNumWsT = new Array(N),16601661rMultWs = new Array(N),1662iMultWs = new Array(N);16631664- _iconvertTo13(this.words, rThisWs, iThisWs, N);1665- _iconvertTo13(num.words, rNumWs, iNumWs, N);1666+ for (var i = 0; i < N; ++i)1667+ zeroes[i] = 0;1668+1669+ _iconvertTo13(this.words, rThisWs, N);1670+ _iconvertTo13(num.words, rNumWs, N);16711672- _FFTL(rThisWs, iThisWs, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);1673+ _FFTL(rThisWs, zeroes, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);16741675//console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))1676//console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))16771678- _FFTL(rNumWs, iNumWs, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);1679+ _FFTL(rNumWs, zeroes, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);16801681//console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))1682//console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))1683@@ -1659,17 +1658,13 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1684//multW = _inormalize20(_iconjugate(multW, N), N);1685//multW = _inormalize18(_iconjugate(multW, N), N);16861687- out.words = _toArray(rMultWs);1688+ out.words = rMultWs;16891690//console.log("-- MUL -- ", multW);16911692return out.strip();1693};16941695-function _toArray(f64a) {1696- return [].slice.call(f64a);1697-}1698-16991700// Multiply `this` by `num`1701BN.prototype.mul = function mul(num) {17021703From 4af09f26ad1d4904496d9b92e1b207971ca6d819 Mon Sep 17 00:00:00 20011704From: Alexey Kudinkin <[email protected]>1705Date: Sun, 14 Dec 2014 22:43:01 +03001706Subject: [PATCH 06/12] Vapourized yet another array17071708---1709lib/bn.js | 26 ++++++++++++++++----------17101 file changed, 16 insertions(+), 10 deletions(-)17111712diff --git a/lib/bn.js b/lib/bn.js1713index 36beb6d..60953fc 1006441714--- a/lib/bn.js1715+++ b/lib/bn.js1716@@ -1572,6 +1572,7 @@ BN.prototype.mulToF = function mulToF(num, out) {1717return res;1718};17191720+1721BN.prototype._bigMulToF = function _bigMulToF(num, out) {1722out.sign = num.sign !== this.sign;1723out.length = this.length + num.length;1724@@ -1599,7 +1600,8 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1725//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);1726//_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);17271728- var zeroes = new Array(N),1729+ var ph = _makePlaceHolderA(N),1730+1731rThisWs = new Array(N),1732rThisWsT = new Array(N), // T for Transformed1733iThisWsT = new Array(N),1734@@ -1608,21 +1610,17 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1735rNumWsT = new Array(N),1736iNumWsT = new Array(N),17371738- rMultWs = new Array(N),1739- iMultWs = new Array(N);1740-1741- for (var i = 0; i < N; ++i)1742- zeroes[i] = 0;1743+ rMultWs = new Array(N);17441745_iconvertTo13(this.words, rThisWs, N);1746_iconvertTo13(num.words, rNumWs, N);17471748- _FFTL(rThisWs, zeroes, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);1749+ _FFTL(rThisWs, ph, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);17501751//console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))1752//console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))17531754- _FFTL(rNumWs, zeroes, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);1755+ _FFTL(rNumWs, ph, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);17561757//console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))1758//console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))1759@@ -1645,11 +1643,11 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {17601761//console.log("X * Y[R/I] Transformed Conjugated", _toArray(rThisWsT), _toArray(iThisWsT))17621763- _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, iMultWs, 0, 0, N, rbt);1764+ _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, ph, 0, 0, N, rbt);17651766//console.log("X * Y[R/I] Inverse FFT", _toArray(rMultWs), _toArray(iMultWs))17671768- _iconjugateX(rMultWs, iMultWs, N);1769+ _iconjugateX(rMultWs, ph, N);17701771_inormalize13X(rMultWs, N);17721773@@ -1665,6 +1663,14 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {1774return out.strip();1775};17761777+function _makePlaceHolderA(N) {1778+ var ph = new Array(N);1779+ for (var i = 0; i < N; ++i)1780+ ph[i] = 0;1781+1782+ return ph;1783+}1784+17851786// Multiply `this` by `num`1787BN.prototype.mul = function mul(num) {17881789From 393e6b3d41b4b260de8354937c1061de822aee47 Mon Sep 17 00:00:00 20011790From: Alexey Kudinkin <[email protected]>1791Date: Sun, 14 Dec 2014 22:46:07 +03001792Subject: [PATCH 07/12] Cleaned up17931794---1795benchmarks/index.js | 181 +++++++++------1796lib/bn.js | 639 +++-------------------------------------------------1797test/_fft.js | 49 ----17983 files changed, 143 insertions(+), 726 deletions(-)1799delete mode 100644 test/_fft.js18001801diff --git a/benchmarks/index.js b/benchmarks/index.js1802index 64b61d9..75e0f0c 1006441803--- a/benchmarks/index.js1804+++ b/benchmarks/index.js1805@@ -56,90 +56,120 @@ if (/fast/i.test(process.argv[3])) {1806benchmark.options.minTime = 1;1807}18081809+var aj = 'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +1810+ '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +1811+ '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +1812+ 'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +1813+ 'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +1814+ 'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +1815+ 'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +1816+ 'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +1817+ '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +1818+ '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +1819+ 'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +1820+ 'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +1821+ '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +1822+ 'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +1823+ 'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +1824+ '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +1825+ '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +1826+ '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +1827+ '100050a430b47bc592995606440272a4994677577a6aaa1b' +1828+ 'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +1829+ 'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +1830+ '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +1831+ 'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +1832+ '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +1833+ '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +1834+ '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +1835+ '1c64145849b3da8c2d343410df892d958db232617f9896f1' +1836+ 'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +1837+ 'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +1838+ 'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +1839+ 'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +1840+ '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0';1841+1842+var bj = '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +1843+ '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +1844+ 'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +1845+ 'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +1846+ 'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +1847+ 'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +1848+ 'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +1849+ '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +1850+ 'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +1851+ '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +1852+ '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +1853+ '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +1854+ 'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +1855+ '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +1856+ 'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +1857+ '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +1858+ '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +1859+ 'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +1860+ 'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +1861+ '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +1862+ 'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +1863+ '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +1864+ 'fbedccbc786951025597522eef283e3f56b44561a0765783' +1865+ '420128638c257e54b972a76e4261892d81222b3e2039c61a' +1866+ 'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +1867+ 'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +1868+ '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +1869+ 'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +1870+ 'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +1871+ '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +1872+ 'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +1873+ '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d';1874+1875+// BN1876+1877var a1 = new bn('012345678901234567890123456789012345678901234567890', 10);1878var b1 = new bn('213509123601923760129376102397651203958123402314875', 10);18791880-var a1x = new bn( 'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +1881- '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +1882- '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +1883- 'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +1884- 'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +1885- 'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +1886- 'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +1887- 'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +1888- '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +1889- '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +1890- 'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +1891- 'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +1892- '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +1893- 'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +1894- 'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +1895- '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +1896- '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +1897- '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +1898- '100050a430b47bc592995606440272a4994677577a6aaa1b' +1899- 'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +1900- 'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +1901- '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +1902- 'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +1903- '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +1904- '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +1905- '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +1906- '1c64145849b3da8c2d343410df892d958db232617f9896f1' +1907- 'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +1908- 'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +1909- 'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +1910- 'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +1911- '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0', 16);1912-1913-var b1x = new bn( '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +1914- '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +1915- 'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +1916- 'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +1917- 'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +1918- 'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +1919- 'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +1920- '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +1921- 'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +1922- '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +1923- '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +1924- '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +1925- 'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +1926- '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +1927- 'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +1928- '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +1929- '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +1930- 'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +1931- 'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +1932- '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +1933- 'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +1934- '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +1935- 'fbedccbc786951025597522eef283e3f56b44561a0765783' +1936- '420128638c257e54b972a76e4261892d81222b3e2039c61a' +1937- 'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +1938- 'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +1939- '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +1940- 'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +1941- 'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +1942- '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +1943- 'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +1944- '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d', 16);1945+var a1j = new bn(aj, 16);1946+var b1j = new bn(bj, 16);1947+1948+// bignum19491950var a2 = new bignum('012345678901234567890123456789012345678901234567890', 10);1951var b2 = new bignum('213509123601923760129376102397651203958123402314875', 10);19521953+var a2j = new bignum(aj, 16);1954+var b2j = new bignum(bj, 16);1955+1956+// bigi1957+1958var a4 = new bigi('012345678901234567890123456789012345678901234567890', 10);1959var b4 = new bigi('213509123601923760129376102397651203958123402314875', 10);19601961+var a4j = new bigi(aj, 16);1962+var b4j = new bigi(bj, 16);1963+1964+// sjcl1965+1966var a5 = new sjcl(a1.toString(16));1967var b5 = new sjcl(b1.toString(16));19681969+var a5j = new sjcl(aj);1970+var b5j = new sjcl(bj);1971+1972+// BigInteger1973+1974var a6 = new BigInteger('012345678901234567890123456789012345678901234567890', 10);1975var b6 = new BigInteger('213509123601923760129376102397651203958123402314875', 10);19761977+var a6j = new BigInteger(aj, 16);1978+var b6j = new BigInteger(bj, 16);1979+1980+// SilentMattBigInteger1981+1982var a8 = SilentMattBigInteger.parse('012345678901234567890123456789012345678901234567890', 10);1983var b8 = SilentMattBigInteger.parse('213509123601923760129376102397651203958123402314875', 10);19841985+var a8j = SilentMattBigInteger.parse(aj, 16);1986+var b8j = SilentMattBigInteger.parse(aj, 16);1987+1988var as1 = a1.mul(a1).iaddn(0x2adbeef);1989var as2 = a2.mul(a2).add(0x2adbeef);1990var as4 = a4.multiply(a4).add(bigi.valueOf(0x2adbeef));1991@@ -273,7 +303,7 @@ add('mul', {1992},1993'bn.js[FFT]': function() {1994a1.mulf(b1);1995- }1996+ },1997'bignum': function() {1998a2.mul(b2);1999},2000@@ -293,10 +323,25 @@ add('mul', {20012002add('mul-jumbo', {2003'bn.js': function() {2004- a1x.mul(b1x);2005+ a1j.mul(b1j);2006},2007'bn.js[FFT]': function() {2008- a1x.mulf(b1x);2009+ a1j.mulf(b1j);2010+ },2011+ 'bignum': function() {2012+ a2j.mul(b2j);2013+ },2014+ 'bigi': function() {2015+ a4j.multiply(b4j);2016+ },2017+ 'sjcl': function() {2018+ a5j.mul(b5j);2019+ },2020+ 'yaffle': function() {2021+ a6j.multiply(b6j);2022+ },2023+ 'silentmatt-biginteger': function() {2024+ a8j.multiply(b8j);2025}2026});20272028diff --git a/lib/bn.js b/lib/bn.js2029index 60953fc..c1aaedd 1006442030--- a/lib/bn.js2031+++ b/lib/bn.js2032@@ -883,151 +883,24 @@ BN.prototype._bigMulTo = function _bigMulTo(num, out) {2033return out.strip();2034};20352036+BN.prototype.mulTo = function mulTo(num, out) {2037+ var res;2038+ var len = this.length + num.length;2039+ if (len < 63)2040+ res = this._smallMulTo(num, out);2041+ else if (len < 1024)2042+ res = this._bigMulTo(num, out);2043+ else2044+ res = this._bigMulToF(num, out);2045+ return res;2046+};20472048-function Complex(r, i) {2049- this.r = r;2050- this.i = i;2051-2052- //this._norm();2053-}2054-2055-// private2056-function _iaddC(rhs) {2057- this.r += rhs.r;2058- this.i += rhs.i;2059-2060- //this._norm();2061-2062- return this;2063-}2064-2065-function _addC(rhs) {2066- var t = new Complex(this.r, this.i);2067- t.iadd(rhs);2068- return t;2069-}2070-2071-function _isubC(rhs) {2072- this.r -= rhs.r;2073- this.i -= rhs.i2074-2075- //this._norm();2076-2077- return this;2078-}2079-2080-function _subC(rhs) {2081- var t = new Complex(this.r, this.i);2082- t.isub(rhs);2083- return t;2084-}2085-2086-function _iconjC() {2087- this.i *= -1;2088- return this;2089-}2090-2091-function _imulC(rhs) {2092- var r = this.r * rhs.r - this.i * rhs.i,2093- i = this.r * rhs.i + this.i * rhs.r;2094-2095- this.r = r;2096- this.i = i;2097-2098- //this._norm();2099-2100- return this;2101-}2102-2103-function _mulC(rhs) {2104- var t = new Complex(this.r, this.i);2105- t.imul(rhs);2106- return t;2107-}2108-2109-function _cloneC() {2110- return new Complex(this.r, this.i);2111-}2112-2113-Complex.prototype.mul = _mulC;2114-Complex.prototype.imul = _imulC;2115-Complex.prototype.add = _addC;2116-Complex.prototype.iadd = _iaddC;2117-Complex.prototype.sub = _subC;2118-Complex.prototype.isub = _isubC;2119-Complex.prototype.iconj = _iconjC;2120-Complex.prototype.clone = _cloneC;2121-2122-//Complex.prototype._isZero = function (v) {2123-// return Math.abs(v) < 1.e-12;2124-//}2125-2126-//Complex.prototype._norm = function () {2127- //if (this._isZero(this.r)) this.r = 0;2128- //if (this._isZero(this.i)) this.i = 0;2129-//}2130-2131-// _FFT(this.words, thisWFT, w, N, 0);2132-function _FFT(ws, p, s, tws, tp, r, N) {2133- if (N === 1) {2134- tws[tp] = ws[p];2135- //console.log("p/tp/ws/tws :", p, tp, ws, tws);2136- } else {2137- var hN = N / 2 >> 0;2138-2139- var rr = r.mul(r);2140-2141- var s_ = 2 * s + 1;2142-2143- //console.log("-- FFT -- # ", N);2144- //console.log("-- R -- ", r);2145-2146- //console.log("-- RR -- # ", rr);2147-2148- _FFT(ws, p, s_, tws, tp, rr, hN); // even2149- _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd2150-2151- var r_ = r.clone();2152-2153- for (var i = 0; i < hN; ++i) {2154- var e = tws[tp + i];2155- var o = tws[tp + i + hN].clone();2156-2157- //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)2158- //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));2159-2160- o.imul(r_);2161-2162- tws[tp + i] = e.add(o);2163- tws[tp + i + hN] = e.sub(o);2164-2165- //console.log(tws);2166-2167- //assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))2168- //assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))2169-2170- r_.imul(r);21712172- //console.log("tws | ", tws)2173- }2174- }2175-}2176+// Private21772178var π = 3.14159265359;21792180-2181-function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {2182- //var hN = N / 2 >> 0;2183-2184- //for (var j = 0; j < 2; ++j)2185- //for (var i = 0, hhN = hN >> 1, dN = hN; i < hhN; ++i, dN >>= 1) {2186- // tws[2 * i] = ws[dN + j];2187- // tws[2 * i + 1] = ws[dN + j + ];2188- //}2189-2190- //console.log("XXXXX")2191- //console.log("WS, TWS", ws, tws)2192-2193+function _FFTL(rws, iws, rtws, itws, N, rbt) {2194_permuteTo(rbt, rws, iws, rtws, itws, N);21952196for (var s = 1; s < N; s <<= 1) {2197@@ -1042,38 +915,24 @@ function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {21982199for (var j = 0; j < s; ++j) {22002201- //var e = tws[p + j];2202-2203var re = rtws[p + j];2204var ie = itws[p + j];22052206- //var o = tws[p + j + s].clone();2207-2208var ro = rtws[p + j + s];2209var io = itws[p + j + s];22102211- //o.imul(r_);2212-2213var rx = rtwdf_ * ro - itwdf_ * io;22142215io = rtwdf_ * io + itwdf_ * ro;2216ro = rx;22172218- //tws[p + j] = e.add(o);2219-2220rtws[p + j] = re + ro;2221itws[p + j] = ie + io;22222223- //tws[p + j + s] = e.sub(o)2224-2225rtws[p + j + s] = re - ro;2226itws[p + j + s] = ie - io;22272228- //assert(tws[p + j].r < (0x4000000 * 0x4000000 * 2))2229- //assert(tws[p + j + s].r < (0x4000000 * 0x4000000 * 2))2230-2231if (j !== l) {2232- //r_.imul(r);2233var rx = rtwdf * rtwdf_ - itwdf * itwdf_;22342235itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;2236@@ -1081,8 +940,6 @@ function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {2237}2238}2239}2240-2241- //console.log(tws)2242}2243}22442245@@ -1097,15 +954,7 @@ function _makeRBT(N) {2246}22472248function _permuteTo(rbt, rws, iws, rtws, itws, N) {2249- //var l = (Math.log(N) / Math.log(2)) >> 0;2250for (var i = 0; i < N; ++i) {2251- //var r = _revbin(i, l, N);2252- //console.log("REVBIN: ", i, r)2253- //if (r > i) {2254- // var t = ws[i];2255- // ws[i] = ws[r];2256- // ws[r] = t;2257- //}2258rtws[i] = rws[rbt[i]];2259itws[i] = iws[rbt[i]];2260}2261@@ -1135,22 +984,7 @@ function _guess13(n, m) {2262return (1 << i + 1 + odd)2263}22642265-function _iconjugate(ws, N) {2266- if (N > 1) {2267- for (var i = 0; i < N / 2; ++i) {2268- var t = ws[i];2269- ws[i] = ws[N - i - 1];2270- ws[N - i - 1] = t;2271-2272- ws[i].i *= -1;2273- ws[N - i - 1].i *= -1;2274- }2275- }2276-2277- return ws;2278-}2279-2280-function _iconjugateX(rws, iws, N) {2281+function _iconjugate(rws, iws, N) {2282if (N > 1) {2283for (var i = 0; i < N / 2; ++i) {2284var t = rws[i];2285@@ -1169,262 +1003,22 @@ function _iconjugateX(rws, iws, N) {2286function _inormalize13(ws, N) {2287var carry = 0;2288for (var i = 0; i < N / 2; ++i) {2289-2290- //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)2291- // + ((ws[2 * i].r / N + .5) >> 0)2292- // + carry;2293-2294- //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {2295- // console.log(1 << 13, 1 * 0x2000);2296- // console.log(Math.round(ws[2 * i + 1].r / N), ((Math.round(ws[2 * i + 1].r / N)) << 7), (Math.round(ws[2 * i + 1].r / N) * 0x2000));2297- // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");2298- //}2299-2300- //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)2301- //2302- //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)2303- // + Math.round(ws[2 * i].r / N)2304- // + carry;2305-2306- var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)2307- + Math.round(ws[2 * i].r / N)2308- + carry;2309-2310- //console.log(2311- // n.toString(16),2312- // carry.toString(16),2313- // (n & 0x3ffffff).toString(16)2314- // );2315-2316- ws[i] = n & 0x3ffffff;2317-2318- if (n < 0x4000000) {2319- carry = 0;2320- } else {2321- carry = Math.floor(n / 0x4000000);2322- }2323- }2324-2325- return ws;2326-}2327-2328-2329-function _inormalize13X(ws, N) {2330- var carry = 0;2331- for (var i = 0; i < N / 2; ++i) {2332-2333- //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)2334- // + ((ws[2 * i].r / N + .5) >> 0)2335- // + carry;2336-2337- //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {2338- // console.log(1 << 13, 1 * 0x2000);2339- // console.log(Math.round(ws[2 * i + 1].r / N), ((Math.round(ws[2 * i + 1].r / N)) << 7), (Math.round(ws[2 * i + 1].r / N) * 0x2000));2340- // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");2341- //}2342-2343- //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)2344- //2345- //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)2346- // + Math.round(ws[2 * i].r / N)2347- // + carry;2348-2349- var n = (Math.round(ws[2 * i + 1] / N) * 0x2000)2350+ var w = (Math.round(ws[2 * i + 1] / N) * 0x2000)2351+ Math.round(ws[2 * i] / N)2352+ carry;23532354- //console.log(2355- // n.toString(16),2356- // carry.toString(16),2357- // (n & 0x3ffffff).toString(16)2358- // );2359+ ws[i] = w & 0x3ffffff;23602361- ws[i] = n & 0x3ffffff;2362-2363- if (n < 0x4000000) {2364+ if (w < 0x4000000) {2365carry = 0;2366} else {2367- carry = Math.floor(n / 0x4000000);2368+ carry = Math.floor(w / 0x4000000);2369}2370}23712372return ws;2373}23742375-function _inormalize20(ws, N) {2376-2377- var carry = 0;2378- var seek = 0;2379-2380- for (var j = 0; j < N; ++j) {2381- ws[j] = Math.round(ws[j].r / N);2382- }2383-2384- for (var i = 0; i < N; ++i) {2385- //var w = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)2386- // + ((ws[2 * i].r / N + .5) >> 0)2387- // + carry;2388-2389- //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {2390- // console.log(1 << 13, 1 * 0x2000);2391- // console.log(Math.round(ws[2 * i + 1].r / N), ((Math.round(ws[2 * i + 1].r / N)) << 7), (Math.round(ws[2 * i + 1].r / N) * 0x2000));2392- // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");2393- //}2394-2395- //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)2396-2397- //var w = ws[i];2398- //2399- //assert(w < (0x4000000 * 0x4000000))2400- //2401- //console.log("Before ", w, w & 0x3ffffff, carry);2402- //2403- //if (i + 1 < N) {2404- // w += ((ws[i + 1] + 0.5) & 0x3ffffff) * 0x100000;2405- //2406- // ws[i + 1] &= 0x4000000;2407- //}2408- //2409- //w += carry;2410- //2411- //ws[i] = w & 0x3ffffff;2412- //2413- //carry = Math.floor(w / 0x4000000);2414- //2415- //console.log("After ", w, w & 0x3ffffff, carry);2416-2417- var w = ws[i];2418-2419- //console.log(w, carry, (w & 0x3ffffff));2420-2421- var j = i;2422-2423- //if (w < 0x4000000)2424- {2425- var pseek = seek;2426- seek += 26 - 20;2427-2428- if (seek > 20) {2429- if (i < N - 1) {2430- w += ws[i + 1] * 0x100000 / (1 << pseek)2431-2432- // !!!2433- ++i;2434-2435- seek -= 20;2436-2437- var d = 1 << seek;2438-2439- w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);2440- ws[i + 1] /= d;2441- }2442- }2443- else2444- {2445- var pd = 1 << (pseek);2446- var d = 1 << (seek);2447-2448- //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)2449-2450- w += (ws[i + 1] & (d - 1)) * 0x100000 / pd;2451- ws[i + 1] /= d;2452- }2453- }2454-2455- //console.log(w, w & 0x3ffffff, carry)2456-2457- assert(w < 0x4000000 * 0x4000000)2458- assert(carry < 0x4000000 * 0x4000000)2459-2460- w += carry;2461-2462- //console.log(w, w & 0x3ffffff, carry)2463-2464- ws[j] = w & 0x3ffffff;2465-2466- carry = Math.floor(w / 0x4000000);2467- }2468-2469- return ws;2470-}2471-2472-function _inormalize18(ws, N) {2473-2474- var carry = 0;2475- var seek = 0;2476-2477- for (var j = 0; j < N; ++j) {2478- ws[j] = Math.round(ws[j].r / N);2479- }2480-2481- for (var i = 0; i < N; ++i) {2482- var w = ws[i];2483-2484- //console.log(w, carry, (w & 0x3ffffff));2485-2486- var j = i;2487-2488- //if (w < 0x4000000)2489- {2490- var pseek = seek;2491- seek += 26 - 18;2492-2493- if (seek > 18) {2494- if (i < N - 1) {2495- w += ws[i + 1] * 0x40000 / (1 << pseek)2496-2497- // !!!2498- ++i;2499-2500- seek -= 18;2501-2502- var d = 1 << seek;2503-2504- w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);2505- ws[i + 1] /= d;2506- }2507- }2508- else2509- {2510- var pd = 1 << (pseek);2511- var d = 1 << (seek);2512-2513- //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)2514-2515- w += (ws[i + 1] & (d - 1)) * 0x40000 / pd;2516- ws[i + 1] /= d;2517- }2518- }2519-2520- //console.log(w, w & 0x3ffffff, carry)2521-2522- assert(w < 0x4000000 * 0x4000000)2523- assert(carry < 0x4000000 * 0x4000000)2524-2525- w += carry;2526-2527- //console.log(w, w & 0x3ffffff, carry)2528-2529- ws[j] = w & 0x3ffffff;2530-2531- carry = Math.floor(w / 0x4000000);2532- }2533-2534- return ws;2535-}2536-2537-2538-function _iconvertToC13(ws, N) {2539- var cws = new Array(N);2540- for (var i = 0; i < N / 2; i++) {2541- var w = ws[i] || 0;2542-2543- cws[2 * i] = new Complex(w & 0x1fff, 0);2544- cws[2 * i + 1] = new Complex(w >>> 13, 0);2545- }2546- return cws;2547-}2548-2549function _iconvertTo13(ws, rws, N) {2550for (var i = 0; i < N / 2; i++) {2551var w = ws[i] | 0;2552@@ -1434,135 +1028,14 @@ function _iconvertTo13(ws, rws, N) {2553}2554}25552556-function _iconvertToC20(ws, N) {2557- var cws = new Array(N);2558-2559- for (var i = 0, j = 0, seek = 20; i < N; ++i) {2560- var w = ws[i] || 0;2561- var l = 26;2562-2563- while (l > 0) {2564- cws[j] = cws[j] || 0;2565-2566- if (seek >= l) {2567- cws[j] += w << (20 - seek);2568-2569- seek -= l;2570- if (seek === 0) seek = 20;2571- l = 0;2572- } else {2573- cws[j] += (w & ((1 << seek) - 1)) << (20 - seek);2574- w /= 1 << seek;2575-2576- ++j;2577- l -= seek;2578- seek = 20;2579- }2580- }2581- }2582-2583- for (i = 0; i < N; ++i) {2584- cws[i] = new Complex(cws[i], 0);2585- }2586-2587- return cws;2588-}2589-2590-function _iconvertToC18(ws, N) {2591- var cws = new Array(N);2592-2593- for (var i = 0, j = 0, seek = 18; i < N; ++i) {2594- var w = ws[i] || 0;2595- var l = 26;2596-2597- while (l > 0) {2598- cws[j] = cws[j] || 0;2599-2600- if (seek >= l) {2601- cws[j] += w << (18 - seek);2602-2603- seek -= l;2604- if (seek === 0) seek = 18;2605- l = 0;2606- } else {2607- cws[j] += (w & ((1 << seek) - 1)) << (18 - seek);2608- w /= 1 << seek;2609-2610- ++j;2611- l -= seek;2612- seek = 18;2613- }2614- }2615- }2616-2617- for (i = 0; i < N; ++i) {2618- cws[i] = new Complex(cws[i], 0);2619- }2620+function _makePlaceHolderA(N) {2621+ var ph = new Array(N);2622+ for (var i = 0; i < N; ++i)2623+ ph[i] = 0;26242625- return cws;2626+ return ph;2627}26282629-//function _iconvertTo13(ws, N) {2630-// var cws = new Array(N);2631-// var carry = 0;2632-//2633-// var i = 0;2634-// for (i = 0; i < N; ++i) {2635-// ws[i] = Math.round(ws[i].r / N);2636-// }2637-//2638-// i = 0;2639-// for (var j = 0; true; ++j) {2640-//2641-// if (carry < 0x2000) {2642-// if (i === N)2643-// break;2644-//2645-// carry += ws[i];2646-// i++;2647-// }2648-//2649-// var lo = carry & 0x1fff; // Here we don't care about overflow, since2650-// // since overflow may only "screw" (trim) high-order2651-// // bits, while we're particularly interested in low-order ones2652-//2653-// //console.log(carry, lo)2654-//2655-// carry = carry / 0x2000; // Since shift would trigger conversion from2656-// // float (64) to int (32)2657-//2658-// cws[j] = lo;2659-// }2660-//2661-// //for (var i = 0; i < N; i++) {2662-// // carry += Math.round(ws[i].r / N);2663-// //2664-// //2665-// // var lo = carry & 0x1fff; // Here we don't care about overflow, since2666-// // // since overflow may only "screw" (trim) high-order2667-// // // bits, while we're particularly interested in low-order ones2668-// //2669-// // console.log(carry, lo)2670-// //2671-// // carry = carry / 0x2000; // Since shift would trigger conversion from2672-// // // float (64) to int (32)2673-// //2674-// // cws[i] = lo;2675-// //}2676-//2677-// return cws;2678-//}2679-2680-BN.prototype.mulTo = function mulTo(num, out) {2681- var res;2682- //if (this.length + num.length < 63)2683- // res = this._smallMulTo(num, out);2684- //else2685- res = this._bigMulTo(num, out);2686- // res = this._bigMulToF(num, out);2687- return res;2688-};2689-2690BN.prototype.mulToF = function mulToF(num, out) {2691var res;2692//if (this.length + num.length < 63)2693@@ -1578,29 +1051,10 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {2694out.length = this.length + num.length;26952696var N = 2 * _guess13(this.length, num.length);2697- //var N = _guess13(this.length * 1.3, num.length * 1.3);2698-2699- //var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));2700-2701- //console.log("-- W -- ", w);2702-2703- //var thisWFT = new Array(N),2704- // numWFT = new Array(N),2705- // //multWFT = new Array(N),2706- // multW = new Array(N);2707-2708- //console.log("A, B: ", this, num);27092710var rbt = _makeRBT(N);27112712- //_FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);2713- //_FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);2714- //_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);2715- //_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);2716- //_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);2717- //_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);2718-2719- var ph = _makePlaceHolderA(N),2720+ var _ = _makePlaceHolderA(N),27212722rThisWs = new Array(N),2723rThisWsT = new Array(N), // T for Transformed2724@@ -1615,62 +1069,29 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {2725_iconvertTo13(this.words, rThisWs, N);2726_iconvertTo13(num.words, rNumWs, N);27272728- _FFTL(rThisWs, ph, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);2729-2730- //console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))2731- //console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))2732-2733- _FFTL(rNumWs, ph, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);2734-2735- //console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))2736- //console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))2737+ _FFTL(rThisWs, _, rThisWsT, iThisWsT, N, rbt);2738+ _FFTL(rNumWs, _, rNumWsT, iNumWsT, N, rbt);27392740for (var i = 0; i < N; ++i) {2741- //thisWFT[i].imul(numWFT[i]);2742var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];27432744iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]2745rThisWsT[i] = rx;2746}27472748- //console.log("X * Y[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))2749-2750- //console.log("-- MULF -- ", multWFT);2751-2752- //_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);2753+ _iconjugate(rThisWsT, iThisWsT, N);27542755- _iconjugateX(rThisWsT, iThisWsT, N);2756+ _FFTL(rThisWsT, iThisWsT, rMultWs, _, N, rbt);27572758- //console.log("X * Y[R/I] Transformed Conjugated", _toArray(rThisWsT), _toArray(iThisWsT))2759+ _iconjugate(rMultWs, _, N);27602761- _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, ph, 0, 0, N, rbt);2762-2763- //console.log("X * Y[R/I] Inverse FFT", _toArray(rMultWs), _toArray(iMultWs))2764-2765- _iconjugateX(rMultWs, ph, N);2766-2767- _inormalize13X(rMultWs, N);2768-2769- //console.log("X * Y[R/I] Conjugated Normalized", _toArray(rMultWs), _toArray(iMultWs))2770-2771- //multW = _inormalize20(_iconjugate(multW, N), N);2772- //multW = _inormalize18(_iconjugate(multW, N), N);2773+ _inormalize13(rMultWs, N);27742775out.words = rMultWs;27762777- //console.log("-- MUL -- ", multW);2778-2779return out.strip();2780};27812782-function _makePlaceHolderA(N) {2783- var ph = new Array(N);2784- for (var i = 0; i < N; ++i)2785- ph[i] = 0;2786-2787- return ph;2788-}2789-27902791// Multiply `this` by `num`2792BN.prototype.mul = function mul(num) {2793diff --git a/test/_fft.js b/test/_fft.js2794deleted file mode 1006442795index 40237ed..00000002796--- a/test/_fft.js2797+++ /dev/null2798@@ -1,49 +0,0 @@2799-var BN = require("../lib/bn.js").BN2800-var fixtures = require("./fixtures.js")2801-2802-//var a = new BN("1");2803-//var b = new BN("1");2804-2805-//var a = new BN("2");2806-//var b = new BN("13");2807-2808-//var a = new BN("123");2809-//var b = new BN("123");2810-2811-//var a = new BN("12345");2812-//var b = new BN("1");2813-2814-//var a = new BN("123456");2815-//var b = new BN("123456");2816-2817-//var a = new BN("12345690");2818-//var b = new BN("1234560");2819-2820-//var a = new BN("123456900");2821-//var b = new BN("12345601");2822-2823-//var a = new BN("0x2000", 16);2824-//var b = new BN("12345678");2825-2826-//var a = new BN("123456789");2827-//var b = new BN("123456789");2828-2829-//var a = new BN(2830-// '13f29a3e0bc10e100ce0', 16);2831-//var b = a.clone();2832-2833-2834-var a = new BN(fixtures.dhGroups.p17.q, 16);2835-var b = a.clone();2836-var qs = fixtures.dhGroups.p17.qs;2837-2838-var c = a.mulf(b);2839-var c_ = a.mul(b);2840-2841-//console.log(c.words);2842-console.log(c);2843-console.log("------")2844-//console.log(c_.words);2845-console.log(c_);2846-2847-//assert(c === new BN(2))28482849From 955d90d26efa344490afa0daabf582c1517037da Mon Sep 17 00:00:00 20012850From: Alexey Kudinkin <[email protected]>2851Date: Tue, 16 Dec 2014 02:26:35 +03002852Subject: [PATCH 08/12] Tidying up28532854---2855lib/bn.js | 65 +++++++++++++++++++++++++++++----------------------------------28561 file changed, 30 insertions(+), 35 deletions(-)28572858diff --git a/lib/bn.js b/lib/bn.js2859index c1aaedd..745641c 1006442860--- a/lib/bn.js2861+++ b/lib/bn.js2862@@ -898,22 +898,20 @@ BN.prototype.mulTo = function mulTo(num, out) {28632864// Private28652866-var π = 3.14159265359;2867-2868function _FFTL(rws, iws, rtws, itws, N, rbt) {2869_permuteTo(rbt, rws, iws, rtws, itws, N);28702871for (var s = 1; s < N; s <<= 1) {2872- var l = s << 1;2873+ var l = s << 1;28742875- var rtwdf = Math.cos(2 * π / l);2876- var itwdf = Math.sin(2 * π / l);2877+ var rtwdf = Math.cos(2 * Math.PI / l);2878+ var itwdf = Math.sin(2 * Math.PI / l);28792880for (var p = 0; p < N; p += l) {2881var rtwdf_ = rtwdf;2882var itwdf_ = itwdf;28832884- for (var j = 0; j < s; ++j) {2885+ for (var j = 0; j < s; j++) {28862887var re = rtws[p + j];2888var ie = itws[p + j];2889@@ -946,7 +944,7 @@ function _FFTL(rws, iws, rtws, itws, N, rbt) {2890function _makeRBT(N) {2891var t = new Array(N);2892var l = (Math.log(N) / Math.log(2)) >> 0;2893- for (var i = 0; i < N; ++i) {2894+ for (var i = 0; i < N; i++) {2895t[i] = _revbin(i, l, N);2896}28972898@@ -954,7 +952,7 @@ function _makeRBT(N) {2899}29002901function _permuteTo(rbt, rws, iws, rtws, itws, N) {2902- for (var i = 0; i < N; ++i) {2903+ for (var i = 0; i < N; i++) {2904rtws[i] = rws[rbt[i]];2905itws[i] = iws[rbt[i]];2906}2907@@ -965,7 +963,7 @@ function _revbin(x, l, N) {2908return x;29092910var rb = 0;2911- for (var i = 0; i < l; ++i) {2912+ for (var i = 0; i < l; i++) {2913rb |= (x & 1) << (l - i - 1);2914x >>= 1;2915}2916@@ -986,33 +984,33 @@ function _guess13(n, m) {29172918function _iconjugate(rws, iws, N) {2919if (N > 1) {2920- for (var i = 0; i < N / 2; ++i) {2921+ for (var i = 0; i < N / 2; i++) {2922var t = rws[i];29232924- rws[i] = rws[N - i - 1];2925- rws[N - i - 1] = t;2926+ rws[i] = rws[N - i - 1];2927+ rws[N - i - 1] = t;29282929t = iws[i];29302931- iws[i] = -iws[N - i - 1];2932- iws[N - i - 1] = -t;2933+ iws[i] = -iws[N - i - 1];2934+ iws[N - i - 1] = -t;2935}2936}2937}29382939function _inormalize13(ws, N) {2940var carry = 0;2941- for (var i = 0; i < N / 2; ++i) {2942- var w = (Math.round(ws[2 * i + 1] / N) * 0x2000)2943- + Math.round(ws[2 * i] / N)2944- + carry;2945+ for (var i = 0; i < N / 2; i++) {2946+ var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +2947+ Math.round(ws[2 * i] / N) +2948+ carry;29492950ws[i] = w & 0x3ffffff;29512952if (w < 0x4000000) {2953carry = 0;2954} else {2955- carry = Math.floor(w / 0x4000000);2956+ carry = w / 0x4000000 | 0;2957}2958}29592960@@ -1023,14 +1021,14 @@ function _iconvertTo13(ws, rws, N) {2961for (var i = 0; i < N / 2; i++) {2962var w = ws[i] | 0;29632964- rws[2 * i] = w & 0x1fff;2965- rws[2 * i + 1] = w >>> 13;2966+ rws[2 * i] = w & 0x1fff;2967+ rws[2 * i + 1] = w >>> 13;2968}2969}29702971function _makePlaceHolderA(N) {2972var ph = new Array(N);2973- for (var i = 0; i < N; ++i)2974+ for (var i = 0; i < N; i++)2975ph[i] = 0;29762977return ph;2978@@ -1038,10 +1036,7 @@ function _makePlaceHolderA(N) {29792980BN.prototype.mulToF = function mulToF(num, out) {2981var res;2982- //if (this.length + num.length < 63)2983- // res = this._smallMulTo(num, out);2984- //else2985- res = this._bigMulToF(num, out);2986+ res = this._bigMulToF(num, out);2987return res;2988};29892990@@ -1054,17 +1049,17 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {29912992var rbt = _makeRBT(N);29932994- var _ = _makePlaceHolderA(N),2995+ var _ = _makePlaceHolderA(N),29962997- rThisWs = new Array(N),2998- rThisWsT = new Array(N), // T for Transformed2999- iThisWsT = new Array(N),3000+ rThisWs = new Array(N),3001+ rThisWsT = new Array(N), // T for Transformed3002+ iThisWsT = new Array(N),30033004- rNumWs = new Array(N),3005- rNumWsT = new Array(N),3006- iNumWsT = new Array(N),3007+ rNumWs = new Array(N),3008+ rNumWsT = new Array(N),3009+ iNumWsT = new Array(N),30103011- rMultWs = new Array(N);3012+ rMultWs = new Array(N);30133014_iconvertTo13(this.words, rThisWs, N);3015_iconvertTo13(num.words, rNumWs, N);3016@@ -1072,7 +1067,7 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {3017_FFTL(rThisWs, _, rThisWsT, iThisWsT, N, rbt);3018_FFTL(rNumWs, _, rNumWsT, iNumWsT, N, rbt);30193020- for (var i = 0; i < N; ++i) {3021+ for (var i = 0; i < N; i++) {3022var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];30233024iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]30253026From 22f4a713b509e7166d05ee800de5dff863a3bd7c Mon Sep 17 00:00:00 20013027From: Alexey Kudinkin <[email protected]>3028Date: Fri, 19 Dec 2014 20:48:02 +03003029Subject: [PATCH 09/12] Extracted FFT multiplier as class; Minor cosmetic fixes30303031---3032lib/bn.js | 158 ++++++++++++++++++++++++++++++++------------------------------30331 file changed, 81 insertions(+), 77 deletions(-)30343035diff --git a/lib/bn.js b/lib/bn.js3036index 745641c..285a08d 1006443037--- a/lib/bn.js3038+++ b/lib/bn.js3039@@ -898,8 +898,43 @@ BN.prototype.mulTo = function mulTo(num, out) {30403041// Private30423043-function _FFTL(rws, iws, rtws, itws, N, rbt) {3044- _permuteTo(rbt, rws, iws, rtws, itws, N);3045+var FFTM = function (x, y) {3046+ this.x = x;3047+ this.y = y;3048+}3049+3050+FFTM.prototype.make_rbt = function (N) {3051+ var t = new Array(N);3052+ var l = (Math.log(N) / Math.log(2)) >> 0;3053+ for (var i = 0; i < N; i++) {3054+ t[i] = this.revbin(i, l, N);3055+ }3056+3057+ return t;3058+}3059+3060+FFTM.prototype.revbin = function (x, l, N) {3061+ if (x === 0 || x === N - 1)3062+ return x;3063+3064+ var rb = 0;3065+ for (var i = 0; i < l; i++) {3066+ rb |= (x & 1) << (l - i - 1);3067+ x >>= 1;3068+ }3069+3070+ return rb;3071+}3072+3073+FFTM.prototype.permute = function (rbt, rws, iws, rtws, itws, N) {3074+ for (var i = 0; i < N; i++) {3075+ rtws[i] = rws[rbt[i]];3076+ itws[i] = iws[rbt[i]];3077+ }3078+}3079+3080+FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {3081+ this.permute(rbt, rws, iws, rtws, itws, N);30823083for (var s = 1; s < N; s <<= 1) {3084var l = s << 1;3085@@ -931,7 +966,7 @@ function _FFTL(rws, iws, rtws, itws, N, rbt) {3086itws[p + j + s] = ie - io;30873088if (j !== l) {3089- var rx = rtwdf * rtwdf_ - itwdf * itwdf_;3090+ rx = rtwdf * rtwdf_ - itwdf * itwdf_;30913092itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;3093rtwdf_ = rx;3094@@ -941,48 +976,18 @@ function _FFTL(rws, iws, rtws, itws, N, rbt) {3095}3096}30973098-function _makeRBT(N) {3099- var t = new Array(N);3100- var l = (Math.log(N) / Math.log(2)) >> 0;3101- for (var i = 0; i < N; i++) {3102- t[i] = _revbin(i, l, N);3103- }3104-3105- return t;3106-}3107-3108-function _permuteTo(rbt, rws, iws, rtws, itws, N) {3109- for (var i = 0; i < N; i++) {3110- rtws[i] = rws[rbt[i]];3111- itws[i] = iws[rbt[i]];3112- }3113-}3114-3115-function _revbin(x, l, N) {3116- if (x === 0 || x === N - 1)3117- return x;3118-3119- var rb = 0;3120- for (var i = 0; i < l; i++) {3121- rb |= (x & 1) << (l - i - 1);3122- x >>= 1;3123- }3124-3125- return rb;3126-}3127-3128-3129-function _guess13(n, m) {3130- var N = Math.max(m, n) | 1, odd = N & 1;3131+FFTM.prototype.guess_len_13b = function (n, m) {3132+ var N = Math.max(m, n) | 1;3133+ var odd = N & 1;3134var i = 0;3135while (N = N / 2 >> 0) {3136i++;3137}31383139- return (1 << i + 1 + odd)3140+ return 1 << i + 1 + odd;3141}31423143-function _iconjugate(rws, iws, N) {3144+FFTM.prototype.conjugate = function (rws, iws, N) {3145if (N > 1) {3146for (var i = 0; i < N / 2; i++) {3147var t = rws[i];3148@@ -998,7 +1003,7 @@ function _iconjugate(rws, iws, N) {3149}3150}31513152-function _inormalize13(ws, N) {3153+FFTM.prototype.normalize_13b = function (ws, N) {3154var carry = 0;3155for (var i = 0; i < N / 2; i++) {3156var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +3157@@ -1017,7 +1022,7 @@ function _inormalize13(ws, N) {3158return ws;3159}31603161-function _iconvertTo13(ws, rws, N) {3162+FFTM.prototype.convert_13b = function (ws, rws, N) {3163for (var i = 0; i < N / 2; i++) {3164var w = ws[i] | 0;31653166@@ -1026,46 +1031,39 @@ function _iconvertTo13(ws, rws, N) {3167}3168}31693170-function _makePlaceHolderA(N) {3171- var ph = new Array(N);3172- for (var i = 0; i < N; i++)3173- ph[i] = 0;3174+FFTM.prototype.mulp = function () {3175+ function stub(N) {3176+ var ph = new Array(N);3177+ for (var i = 0; i < N; i++)3178+ ph[i] = 0;31793180- return ph;3181-}3182+ return ph;3183+ }31843185-BN.prototype.mulToF = function mulToF(num, out) {3186- var res;3187- res = this._bigMulToF(num, out);3188- return res;3189-};3190+ var x = this.x;3191+ var y = this.y;31923193+ var N = 2 * this.guess_len_13b(x.length, y.length);31943195-BN.prototype._bigMulToF = function _bigMulToF(num, out) {3196- out.sign = num.sign !== this.sign;3197- out.length = this.length + num.length;3198+ var rbt = this.make_rbt(N);31993200- var N = 2 * _guess13(this.length, num.length);3201+ var _ = stub(N),32023203- var rbt = _makeRBT(N);3204+ rThisWs = new Array(N),3205+ rThisWsT = new Array(N), // T for Transformed3206+ iThisWsT = new Array(N),32073208- var _ = _makePlaceHolderA(N),3209+ rNumWs = new Array(N),3210+ rNumWsT = new Array(N),3211+ iNumWsT = new Array(N),32123213- rThisWs = new Array(N),3214- rThisWsT = new Array(N), // T for Transformed3215- iThisWsT = new Array(N),3216+ rMultWs = new Array(N);32173218- rNumWs = new Array(N),3219- rNumWsT = new Array(N),3220- iNumWsT = new Array(N),3221+ this.convert_13b(x.words, rThisWs, N);3222+ this.convert_13b(y.words, rNumWs, N);32233224- rMultWs = new Array(N);3225-3226- _iconvertTo13(this.words, rThisWs, N);3227- _iconvertTo13(num.words, rNumWs, N);3228-3229- _FFTL(rThisWs, _, rThisWsT, iThisWsT, N, rbt);3230- _FFTL(rNumWs, _, rNumWsT, iNumWsT, N, rbt);3231+ this.transform(rThisWs, _, rThisWsT, iThisWsT, N, rbt);3232+ this.transform(rNumWs, _, rNumWsT, iNumWsT, N, rbt);32333234for (var i = 0; i < N; i++) {3235var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];3236@@ -1074,15 +1072,22 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {3237rThisWsT[i] = rx;3238}32393240- _iconjugate(rThisWsT, iThisWsT, N);3241+ this.conjugate(rThisWsT, iThisWsT, N);3242+3243+ this.transform(rThisWsT, iThisWsT, rMultWs, _, N, rbt);3244+3245+ this.conjugate(rMultWs, _, N);32463247- _FFTL(rThisWsT, iThisWsT, rMultWs, _, N, rbt);3248+ this.normalize_13b(rMultWs, N);32493250- _iconjugate(rMultWs, _, N);3251+ return rMultWs;3252+}32533254- _inormalize13(rMultWs, N);3255+BN.prototype._bigMulToF = function _bigMulToF(num, out) {3256+ out.sign = num.sign !== this.sign;3257+ out.length = this.length + num.length;32583259- out.words = rMultWs;3260+ out.words = (new FFTM(this, num)).mulp();32613262return out.strip();3263};3264@@ -1098,9 +1103,8 @@ BN.prototype.mul = function mul(num) {3265// Multiply employing FFT3266BN.prototype.mulf = function mulf(num) {3267var out = new BN(null);3268- //out.words = new Array(this.length + num.length);3269out.words = null;3270- return this.mulToF(num, out);3271+ return this._bigMulToF(num, out);3272};32733274// In-place Multiplication32753276From c51b380a9acb25b1c09cb805ec708e836e921a00 Mon Sep 17 00:00:00 20013277From: Alexey Kudinkin <[email protected]>3278Date: Sun, 11 Jan 2015 06:12:05 +03003279Subject: [PATCH 10/12] Minor style fixes32803281---3282lib/bn.js | 36 ++++++++++++++++++------------------32831 file changed, 18 insertions(+), 18 deletions(-)32843285diff --git a/lib/bn.js b/lib/bn.js3286index 285a08d..7705741 1006443287--- a/lib/bn.js3288+++ b/lib/bn.js3289@@ -898,12 +898,12 @@ BN.prototype.mulTo = function mulTo(num, out) {32903291// Private32923293-var FFTM = function (x, y) {3294+function FFTM(x, y) {3295this.x = x;3296this.y = y;3297}32983299-FFTM.prototype.make_rbt = function (N) {3300+FFTM.prototype.makeRBT = function makeRBT(N) {3301var t = new Array(N);3302var l = (Math.log(N) / Math.log(2)) >> 0;3303for (var i = 0; i < N; i++) {3304@@ -913,7 +913,7 @@ FFTM.prototype.make_rbt = function (N) {3305return t;3306}33073308-FFTM.prototype.revbin = function (x, l, N) {3309+FFTM.prototype.revbin = function revbin(x, l, N) {3310if (x === 0 || x === N - 1)3311return x;33123313@@ -926,14 +926,14 @@ FFTM.prototype.revbin = function (x, l, N) {3314return rb;3315}33163317-FFTM.prototype.permute = function (rbt, rws, iws, rtws, itws, N) {3318+FFTM.prototype.permute = function permute(rbt, rws, iws, rtws, itws, N) {3319for (var i = 0; i < N; i++) {3320rtws[i] = rws[rbt[i]];3321itws[i] = iws[rbt[i]];3322}3323}33243325-FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {3326+FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {3327this.permute(rbt, rws, iws, rtws, itws, N);33283329for (var s = 1; s < N; s <<= 1) {3330@@ -947,7 +947,6 @@ FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {3331var itwdf_ = itwdf;33323333for (var j = 0; j < s; j++) {3334-3335var re = rtws[p + j];3336var ie = itws[p + j];33373338@@ -976,7 +975,7 @@ FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {3339}3340}33413342-FFTM.prototype.guess_len_13b = function (n, m) {3343+FFTM.prototype.guessLen13b = function guessLen13b(n, m) {3344var N = Math.max(m, n) | 1;3345var odd = N & 1;3346var i = 0;3347@@ -988,18 +987,19 @@ FFTM.prototype.guess_len_13b = function (n, m) {3348}33493350FFTM.prototype.conjugate = function (rws, iws, N) {3351- if (N > 1) {3352- for (var i = 0; i < N / 2; i++) {3353- var t = rws[i];3354+ if (N <= 1)3355+ return;33563357- rws[i] = rws[N - i - 1];3358- rws[N - i - 1] = t;3359+ for (var i = 0; i < N / 2; i++) {3360+ var t = rws[i];33613362- t = iws[i];3363+ rws[i] = rws[N - i - 1];3364+ rws[N - i - 1] = t;33653366- iws[i] = -iws[N - i - 1];3367- iws[N - i - 1] = -t;3368- }3369+ t = iws[i];3370+3371+ iws[i] = -iws[N - i - 1];3372+ iws[N - i - 1] = -t;3373}3374}33753376@@ -1043,9 +1043,9 @@ FFTM.prototype.mulp = function () {3377var x = this.x;3378var y = this.y;33793380- var N = 2 * this.guess_len_13b(x.length, y.length);3381+ var N = 2 * this.guessLen13b(x.length, y.length);33823383- var rbt = this.make_rbt(N);3384+ var rbt = this.makeRBT(N);33853386var _ = stub(N),338733883389From 72f5498499baec7b4052550892ca52caff33d21c Mon Sep 17 00:00:00 20013390From: Alexey Kudinkin <[email protected]>3391Date: Mon, 12 Jan 2015 17:21:43 +03003392Subject: [PATCH 11/12] Continuous style fixes33933394---3395lib/bn.js | 16 +++++++---------33961 file changed, 7 insertions(+), 9 deletions(-)33973398diff --git a/lib/bn.js b/lib/bn.js3399index 7705741..7081948 1006443400--- a/lib/bn.js3401+++ b/lib/bn.js3402@@ -905,7 +905,7 @@ function FFTM(x, y) {34033404FFTM.prototype.makeRBT = function makeRBT(N) {3405var t = new Array(N);3406- var l = (Math.log(N) / Math.log(2)) >> 0;3407+ var l = (Math.log(N) / Math.log(2)) | 0;3408for (var i = 0; i < N; i++) {3409t[i] = this.revbin(i, l, N);3410}3411@@ -979,7 +979,7 @@ FFTM.prototype.guessLen13b = function guessLen13b(n, m) {3412var N = Math.max(m, n) | 1;3413var odd = N & 1;3414var i = 0;3415- while (N = N / 2 >> 0) {3416+ while (N = N / 2 | 0) {3417i++;3418}34193420@@ -1003,7 +1003,7 @@ FFTM.prototype.conjugate = function (rws, iws, N) {3421}3422}34233424-FFTM.prototype.normalize_13b = function (ws, N) {3425+FFTM.prototype.normalize13b = function (ws, N) {3426var carry = 0;3427for (var i = 0; i < N / 2; i++) {3428var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +3429@@ -1022,7 +1022,7 @@ FFTM.prototype.normalize_13b = function (ws, N) {3430return ws;3431}34323433-FFTM.prototype.convert_13b = function (ws, rws, N) {3434+FFTM.prototype.convert13b = function (ws, rws, N) {3435for (var i = 0; i < N / 2; i++) {3436var w = ws[i] | 0;34373438@@ -1059,8 +1059,8 @@ FFTM.prototype.mulp = function () {34393440rMultWs = new Array(N);34413442- this.convert_13b(x.words, rThisWs, N);3443- this.convert_13b(y.words, rNumWs, N);3444+ this.convert13b(x.words, rThisWs, N);3445+ this.convert13b(y.words, rNumWs, N);34463447this.transform(rThisWs, _, rThisWsT, iThisWsT, N, rbt);3448this.transform(rNumWs, _, rNumWsT, iNumWsT, N, rbt);3449@@ -1078,7 +1078,7 @@ FFTM.prototype.mulp = function () {34503451this.conjugate(rMultWs, _, N);34523453- this.normalize_13b(rMultWs, N);3454+ this.normalize13b(rMultWs, N);34553456return rMultWs;3457}3458@@ -1086,7 +1086,6 @@ FFTM.prototype.mulp = function () {3459BN.prototype._bigMulToF = function _bigMulToF(num, out) {3460out.sign = num.sign !== this.sign;3461out.length = this.length + num.length;3462-3463out.words = (new FFTM(this, num)).mulp();34643465return out.strip();3466@@ -1103,7 +1102,6 @@ BN.prototype.mul = function mul(num) {3467// Multiply employing FFT3468BN.prototype.mulf = function mulf(num) {3469var out = new BN(null);3470- out.words = null;3471return this._bigMulToF(num, out);3472};347334743475From b3b5d959b6cb9dd2f8fc270fe8a64b9a54151d1c Mon Sep 17 00:00:00 20013476From: Alexey Kudinkin <[email protected]>3477Date: Mon, 9 Feb 2015 23:43:13 +03003478Subject: [PATCH 12/12] Sligthly refurbished overall style; Fixed lint issues34793480---3481lib/bn.js | 63 +++++++++++++++++++++++++++++++--------------------------------34821 file changed, 31 insertions(+), 32 deletions(-)34833484diff --git a/lib/bn.js b/lib/bn.js3485index 7081948..5b553e4 1006443486--- a/lib/bn.js3487+++ b/lib/bn.js3488@@ -911,7 +911,7 @@ FFTM.prototype.makeRBT = function makeRBT(N) {3489}34903491return t;3492-}3493+};34943495FFTM.prototype.revbin = function revbin(x, l, N) {3496if (x === 0 || x === N - 1)3497@@ -924,14 +924,14 @@ FFTM.prototype.revbin = function revbin(x, l, N) {3498}34993500return rb;3501-}3502+};35033504FFTM.prototype.permute = function permute(rbt, rws, iws, rtws, itws, N) {3505for (var i = 0; i < N; i++) {3506rtws[i] = rws[rbt[i]];3507itws[i] = iws[rbt[i]];3508}3509-}3510+};35113512FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {3513this.permute(rbt, rws, iws, rtws, itws, N);3514@@ -964,6 +964,7 @@ FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {3515rtws[p + j + s] = re - ro;3516itws[p + j + s] = ie - io;35173518+ /* jshint maxdepth : false */3519if (j !== l) {3520rx = rtwdf * rtwdf_ - itwdf * itwdf_;35213522@@ -973,18 +974,18 @@ FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {3523}3524}3525}3526-}3527+};35283529FFTM.prototype.guessLen13b = function guessLen13b(n, m) {3530var N = Math.max(m, n) | 1;3531var odd = N & 1;3532var i = 0;3533- while (N = N / 2 | 0) {3534+ for (N = N / 2 | 0; N; N = N / 2 | 0) {3535i++;3536}35373538return 1 << i + 1 + odd;3539-}3540+};35413542FFTM.prototype.conjugate = function (rws, iws, N) {3543if (N <= 1)3544@@ -1001,7 +1002,7 @@ FFTM.prototype.conjugate = function (rws, iws, N) {3545iws[i] = -iws[N - i - 1];3546iws[N - i - 1] = -t;3547}3548-}3549+};35503551FFTM.prototype.normalize13b = function (ws, N) {3552var carry = 0;3553@@ -1020,7 +1021,7 @@ FFTM.prototype.normalize13b = function (ws, N) {3554}35553556return ws;3557-}3558+};35593560FFTM.prototype.convert13b = function (ws, rws, N) {3561for (var i = 0; i < N / 2; i++) {3562@@ -1029,7 +1030,7 @@ FFTM.prototype.convert13b = function (ws, rws, N) {3563rws[2 * i] = w & 0x1fff;3564rws[2 * i + 1] = w >>> 13;3565}3566-}3567+};35683569FFTM.prototype.mulp = function () {3570function stub(N) {3571@@ -1047,47 +1048,45 @@ FFTM.prototype.mulp = function () {35723573var rbt = this.makeRBT(N);35743575- var _ = stub(N),3576+ var _ = stub(N);35773578- rThisWs = new Array(N),3579- rThisWsT = new Array(N), // T for Transformed3580- iThisWsT = new Array(N),3581+ var rws = new Array(N);3582+ var rwst = new Array(N);3583+ var iwst = new Array(N);35843585- rNumWs = new Array(N),3586- rNumWsT = new Array(N),3587- iNumWsT = new Array(N),3588+ var nrws = new Array(N);3589+ var nrwst = new Array(N);3590+ var niwst = new Array(N);35913592- rMultWs = new Array(N);3593+ var rmws = new Array(N);35943595- this.convert13b(x.words, rThisWs, N);3596- this.convert13b(y.words, rNumWs, N);3597+ this.convert13b(x.words, rws, N);3598+ this.convert13b(y.words, nrws, N);35993600- this.transform(rThisWs, _, rThisWsT, iThisWsT, N, rbt);3601- this.transform(rNumWs, _, rNumWsT, iNumWsT, N, rbt);3602+ this.transform(rws, _, rwst, iwst, N, rbt);3603+ this.transform(nrws, _, nrwst, niwst, N, rbt);36043605for (var i = 0; i < N; i++) {3606- var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];3607-3608- iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]3609- rThisWsT[i] = rx;3610+ var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];3611+ iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];3612+ rwst[i] = rx;3613}36143615- this.conjugate(rThisWsT, iThisWsT, N);3616+ this.conjugate(rwst, iwst, N);36173618- this.transform(rThisWsT, iThisWsT, rMultWs, _, N, rbt);3619+ this.transform(rwst, iwst, rmws, _, N, rbt);36203621- this.conjugate(rMultWs, _, N);3622+ this.conjugate(rmws, _, N);36233624- this.normalize13b(rMultWs, N);3625+ this.normalize13b(rmws, N);36263627- return rMultWs;3628-}3629+ return rmws;3630+};36313632BN.prototype._bigMulToF = function _bigMulToF(num, out) {3633out.sign = num.sign !== this.sign;3634out.length = this.length + num.length;3635out.words = (new FFTM(this, num)).mulp();3636-3637return out.strip();3638};3639364036413642