Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80555 views
1
From f26e6ec81a999b09c626e5138f04b59abb1f5025 Mon Sep 17 00:00:00 2001
2
From: Alexey Kudinkin <[email protected]>
3
Date: Tue, 9 Dec 2014 04:27:17 +0300
4
Subject: [PATCH 01/12] First scratches FFT
5
6
---
7
lib/bn.js | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
8
1 file changed, 266 insertions(+), 3 deletions(-)
9
10
diff --git a/lib/bn.js b/lib/bn.js
11
index 2e990f6..9b9b857 100644
12
--- a/lib/bn.js
13
+++ b/lib/bn.js
14
@@ -883,15 +883,270 @@ BN.prototype._bigMulTo = function _bigMulTo(num, out) {
15
return out.strip();
16
};
17
18
+
19
+function Complex(r, i) {
20
+ this.r = r;
21
+ this.i = i;
22
+
23
+ //this._norm();
24
+}
25
+
26
+// private
27
+function _iaddC(rhs) {
28
+ this.r += rhs.r;
29
+ this.i += rhs.i;
30
+
31
+ //this._norm();
32
+
33
+ return this;
34
+}
35
+
36
+function _addC(rhs) {
37
+ var t = new Complex(this.r, this.i);
38
+ t.iadd(rhs);
39
+ return t;
40
+}
41
+
42
+function _isubC(rhs) {
43
+ this.r -= rhs.r;
44
+ this.i -= rhs.i
45
+
46
+ //this._norm();
47
+
48
+ return this;
49
+}
50
+
51
+function _subC(rhs) {
52
+ var t = new Complex(this.r, this.i);
53
+ t.isub(rhs);
54
+ return t;
55
+}
56
+
57
+function _iconjC() {
58
+ this.i *= -1;
59
+ return this;
60
+}
61
+
62
+function _imulC(rhs) {
63
+ var r = this.r * rhs.r - this.i * rhs.i,
64
+ i = this.r * rhs.i + this.i * rhs.r;
65
+
66
+ this.r = r;
67
+ this.i = i;
68
+
69
+ //this._norm();
70
+
71
+ return this;
72
+}
73
+
74
+function _mulC(rhs) {
75
+ var t = new Complex(this.r, this.i);
76
+ t.imul(rhs);
77
+ return t;
78
+}
79
+
80
+function _cloneC() {
81
+ return new Complex(this.r, this.i);
82
+}
83
+
84
+Complex.prototype.mul = _mulC;
85
+Complex.prototype.imul = _imulC;
86
+Complex.prototype.add = _addC;
87
+Complex.prototype.iadd = _iaddC;
88
+Complex.prototype.sub = _subC;
89
+Complex.prototype.isub = _isubC;
90
+Complex.prototype.iconj = _iconjC;
91
+Complex.prototype.clone = _cloneC;
92
+
93
+Complex.prototype._isZero = function (v) {
94
+ return Math.abs(v) < 1.e-12;
95
+}
96
+
97
+Complex.prototype._norm = function () {
98
+ //if (this._isZero(this.r)) this.r = 0;
99
+ //if (this._isZero(this.i)) this.i = 0;
100
+}
101
+
102
+Complex.ZERO = new Complex(0, 0);
103
+
104
+// _FFT(this.words, thisWFT, w, N, 0);
105
+function _FFT(ws, p, s, tws, tp, r, N) {
106
+ if (N === 1) {
107
+ tws[tp] = ws[p];
108
+ //console.log("p/tp/ws/tws :", p, tp, ws, tws);
109
+ } else {
110
+ var hN = N / 2 >> 0;
111
+
112
+ var rr = r.mul(r);
113
+
114
+ var s_ = 2 * s + 1;
115
+
116
+ //console.log("-- FFT -- # ", N);
117
+ //console.log("-- R -- ", r);
118
+
119
+ //console.log("-- RR -- # ", rr);
120
+
121
+ _FFT(ws, p, s_, tws, tp, rr, hN); // even
122
+ _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd
123
+
124
+ var r_ = r.clone();
125
+
126
+ for (var i = 0; i < hN; ++i) {
127
+ var e = tws[tp + i];
128
+ var o = tws[tp + i + hN].clone();
129
+
130
+ //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)
131
+ //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));
132
+
133
+ o.imul(r_);
134
+
135
+ tws[tp + i] = e.add(o);
136
+ tws[tp + i + hN] = e.sub(o);
137
+
138
+ r_.imul(r);
139
+
140
+ //console.log("tws | ", tws)
141
+ }
142
+ }
143
+}
144
+
145
+var π = 3.14159265359;
146
+
147
+function _guess(n, m) {
148
+ var N = (n < m ? n : m) | 1, odd = N & 1;
149
+ var i = 0;
150
+ for (; N; N = N / 2 >> 0) {
151
+ i++;
152
+ }
153
+
154
+ return (1 << i + odd)
155
+}
156
+
157
+function _iconjugate(ws, N) {
158
+ if (N > 1) {
159
+ for (var i = 0; i < N / 2; ++i) {
160
+ var t = ws[i];
161
+ ws[i] = ws[N - i - 1];
162
+ ws[N - i - 1] = t;
163
+
164
+ ws[i].i *= -1;
165
+ ws[N - i - 1].i *= -1;
166
+ }
167
+ }
168
+
169
+ return ws;
170
+}
171
+
172
+function _inormalize(ws, N) {
173
+ var carry = 0;
174
+ for (var i = 0; i < N / 2; ++i) {
175
+
176
+ //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)
177
+ // + ((ws[2 * i].r / N + .5) >> 0)
178
+ // + carry;
179
+
180
+ //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {
181
+ // console.log(1 << 13, 1 * 0x2000);
182
+ // 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));
183
+ // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");
184
+ //}
185
+
186
+
187
+ //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)
188
+
189
+ var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)
190
+ + Math.round(ws[2 * i].r / N)
191
+ + carry;
192
+
193
+ //console.log(
194
+ // n.toString(16),
195
+ // carry.toString(16),
196
+ // (n & 0x3ffffff).toString(16)
197
+ // );
198
+
199
+ ws[i] = n & 0x3ffffff;
200
+
201
+ if (n < 0x4000000) {
202
+ carry = 0;
203
+ } else {
204
+ carry = Math.floor(n / 0x4000000);
205
+ }
206
+ }
207
+
208
+ return ws;
209
+}
210
+
211
+function _iconvertToC(ws, N) {
212
+ var cws = new Array(N);
213
+ for (var i = 0; i < N / 2; i++) {
214
+ var w = ws[i] || 0;
215
+
216
+ cws[2 * i] = new Complex(w & 0x1fff, 0);
217
+ cws[2 * i + 1] = new Complex(w >>> 13, 0);
218
+ }
219
+ return cws;
220
+}
221
+
222
BN.prototype.mulTo = function mulTo(num, out) {
223
var res;
224
- if (this.length + num.length < 63)
225
- res = this._smallMulTo(num, out);
226
- else
227
+ //if (this.length + num.length < 63)
228
+ // res = this._smallMulTo(num, out);
229
+ //else
230
res = this._bigMulTo(num, out);
231
+ // res = this._bigMulToF(num, out);
232
return res;
233
};
234
235
+BN.prototype.mulToF = function mulToF(num, out) {
236
+ var res;
237
+ //if (this.length + num.length < 63)
238
+ // res = this._smallMulTo(num, out);
239
+ //else
240
+ res = this._bigMulToF(num, out);
241
+ return res;
242
+};
243
+
244
+BN.prototype._bigMulToF = function _bigMulToF(num, out) {
245
+ out.sign = num.sign !== this.sign;
246
+ out.length = this.length + num.length;
247
+
248
+ var N = 2 * _guess(this.length, num.length);
249
+
250
+ var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));
251
+
252
+ //console.log("-- W -- ", w);
253
+
254
+ var thisWFT = new Array(N),
255
+ numWFT = new Array(N),
256
+ //multWFT = new Array(N),
257
+ multW = new Array(N);
258
+
259
+ //console.log("A, B: ", this, num);
260
+
261
+ _FFT(_iconvertToC(this.words, N), 0, 0, thisWFT, 0, w, N);
262
+ _FFT(_iconvertToC(num.words, N), 0, 0, numWFT, 0, w, N);
263
+
264
+ for (var i = 0; i < N; ++i) {
265
+ //multWFT[i] = thisWFT[i].mul(numWFT[i]);
266
+ thisWFT[i].imul(numWFT[i]);
267
+ }
268
+
269
+ //console.log("-- MULF -- ", multWFT);
270
+
271
+ //_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);
272
+ _FFT(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N);
273
+
274
+ //console.log(multW);
275
+
276
+ multW = _inormalize(_iconjugate(multW, N), N);
277
+
278
+ out.words = multW;
279
+
280
+ //console.log("-- MUL -- ", multW);
281
+
282
+ return out.strip();
283
+};
284
+
285
// Multiply `this` by `num`
286
BN.prototype.mul = function mul(num) {
287
var out = new BN(null);
288
@@ -899,6 +1154,14 @@ BN.prototype.mul = function mul(num) {
289
return this.mulTo(num, out);
290
};
291
292
+// Multiply employing FFT
293
+BN.prototype.mulf = function mulf(num) {
294
+ var out = new BN(null);
295
+ //out.words = new Array(this.length + num.length);
296
+ out.words = null;
297
+ return this.mulToF(num, out);
298
+};
299
+
300
// In-place Multiplication
301
BN.prototype.imul = function imul(num) {
302
if (this.cmpn(0) === 0 || num.cmpn(0) === 0) {
303
304
From 21f40777824dfdc61c93a009e82c25c30d0615ed Mon Sep 17 00:00:00 2001
305
From: Alexey Kudinkin <[email protected]>
306
Date: Fri, 12 Dec 2014 00:25:08 +0300
307
Subject: [PATCH 02/12] Continuous probing
308
309
---
310
benchmarks/index.js | 78 +++++++++++
311
lib/bn.js | 378 ++++++++++++++++++++++++++++++++++++++++++++++++++--
312
test/_fft.js | 43 ++++++
313
3 files changed, 486 insertions(+), 13 deletions(-)
314
create mode 100644 test/_fft.js
315
316
diff --git a/benchmarks/index.js b/benchmarks/index.js
317
index b8cb23d..64b61d9 100644
318
--- a/benchmarks/index.js
319
+++ b/benchmarks/index.js
320
@@ -59,6 +59,72 @@ if (/fast/i.test(process.argv[3])) {
321
var a1 = new bn('012345678901234567890123456789012345678901234567890', 10);
322
var b1 = new bn('213509123601923760129376102397651203958123402314875', 10);
323
324
+var a1x = new bn( 'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +
325
+ '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +
326
+ '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +
327
+ 'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +
328
+ 'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +
329
+ 'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +
330
+ 'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +
331
+ 'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +
332
+ '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +
333
+ '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +
334
+ 'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +
335
+ 'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +
336
+ '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +
337
+ 'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +
338
+ 'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +
339
+ '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +
340
+ '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +
341
+ '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +
342
+ '100050a430b47bc592995606440272a4994677577a6aaa1b' +
343
+ 'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +
344
+ 'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +
345
+ '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +
346
+ 'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +
347
+ '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +
348
+ '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +
349
+ '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +
350
+ '1c64145849b3da8c2d343410df892d958db232617f9896f1' +
351
+ 'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +
352
+ 'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +
353
+ 'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +
354
+ 'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +
355
+ '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0', 16);
356
+
357
+var b1x = new bn( '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +
358
+ '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +
359
+ 'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +
360
+ 'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +
361
+ 'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +
362
+ 'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +
363
+ 'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +
364
+ '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +
365
+ 'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +
366
+ '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +
367
+ '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +
368
+ '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +
369
+ 'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +
370
+ '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +
371
+ 'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +
372
+ '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +
373
+ '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +
374
+ 'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +
375
+ 'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +
376
+ '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +
377
+ 'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +
378
+ '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +
379
+ 'fbedccbc786951025597522eef283e3f56b44561a0765783' +
380
+ '420128638c257e54b972a76e4261892d81222b3e2039c61a' +
381
+ 'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +
382
+ 'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +
383
+ '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +
384
+ 'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +
385
+ 'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +
386
+ '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +
387
+ 'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +
388
+ '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d', 16);
389
+
390
var a2 = new bignum('012345678901234567890123456789012345678901234567890', 10);
391
var b2 = new bignum('213509123601923760129376102397651203958123402314875', 10);
392
393
@@ -205,6 +271,9 @@ add('mul', {
394
'bn.js': function() {
395
a1.mul(b1);
396
},
397
+ 'bn.js[FFT]': function() {
398
+ a1.mulf(b1);
399
+ }
400
'bignum': function() {
401
a2.mul(b2);
402
},
403
@@ -222,6 +291,15 @@ add('mul', {
404
}
405
});
406
407
+add('mul-jumbo', {
408
+ 'bn.js': function() {
409
+ a1x.mul(b1x);
410
+ },
411
+ 'bn.js[FFT]': function() {
412
+ a1x.mulf(b1x);
413
+ }
414
+});
415
+
416
add('sqr', {
417
'bn.js': function() {
418
a1.mul(a1);
419
diff --git a/lib/bn.js b/lib/bn.js
420
index 9b9b857..c803573 100644
421
--- a/lib/bn.js
422
+++ b/lib/bn.js
423
@@ -958,16 +958,14 @@ Complex.prototype.isub = _isubC;
424
Complex.prototype.iconj = _iconjC;
425
Complex.prototype.clone = _cloneC;
426
427
-Complex.prototype._isZero = function (v) {
428
- return Math.abs(v) < 1.e-12;
429
-}
430
+//Complex.prototype._isZero = function (v) {
431
+// return Math.abs(v) < 1.e-12;
432
+//}
433
434
-Complex.prototype._norm = function () {
435
+//Complex.prototype._norm = function () {
436
//if (this._isZero(this.r)) this.r = 0;
437
//if (this._isZero(this.i)) this.i = 0;
438
-}
439
-
440
-Complex.ZERO = new Complex(0, 0);
441
+//}
442
443
// _FFT(this.words, thisWFT, w, N, 0);
444
function _FFT(ws, p, s, tws, tp, r, N) {
445
@@ -1003,6 +1001,11 @@ function _FFT(ws, p, s, tws, tp, r, N) {
446
tws[tp + i] = e.add(o);
447
tws[tp + i + hN] = e.sub(o);
448
449
+ //console.log(tws);
450
+
451
+ assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))
452
+ assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))
453
+
454
r_.imul(r);
455
456
//console.log("tws | ", tws)
457
@@ -1010,6 +1013,63 @@ function _FFT(ws, p, s, tws, tp, r, N) {
458
}
459
}
460
461
+
462
+function _FFTL(ws, p, s, tws, tp, r, N) {
463
+ //if (N === 1) {
464
+ // tws[tp] = ws[p];
465
+ // //console.log("p/tp/ws/tws :", p, tp, ws, tws);
466
+ //} else {
467
+ // var hN = N / 2 >> 0;
468
+ //
469
+ // var rr = r.mul(r);
470
+ //
471
+ // var s_ = 2 * s + 1;
472
+ //
473
+ // //console.log("-- FFT -- # ", N);
474
+ // //console.log("-- R -- ", r);
475
+ //
476
+ // //console.log("-- RR -- # ", rr);
477
+ //
478
+ // _FFT(ws, p, s_, tws, tp, rr, hN); // even
479
+ // _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd
480
+ //
481
+ // var r_ = r.clone();
482
+ //
483
+ // for (var i = 0; i < hN; ++i) {
484
+ // var e = tws[tp + i];
485
+ // var o = tws[tp + i + hN].clone();
486
+ //
487
+ // //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)
488
+ // //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));
489
+ //
490
+ // o.imul(r_);
491
+ //
492
+ // tws[tp + i] = e.add(o);
493
+ // tws[tp + i + hN] = e.sub(o);
494
+ //
495
+ // r_.imul(r);
496
+ //
497
+ // //console.log("tws | ", tws)
498
+ // }
499
+ //}
500
+
501
+ var hN = N / 2 >> 0;
502
+
503
+ for (var i = 0; i < hN; i++) {
504
+ tws[2 * i] = ws[i];
505
+ tws[2 * i + 1] = ws[i + hN];
506
+ }
507
+
508
+ var p = 0;
509
+
510
+ for (var l = 1; l < N + 1; l << 1, p = 0) {
511
+ for (var j = p; j < p + l; ++j, p += l) {
512
+ var e = tws[j];
513
+ var o = tws[j + l].clone();
514
+ }
515
+ }
516
+}
517
+
518
var π = 3.14159265359;
519
520
function _guess(n, m) {
521
@@ -1037,7 +1097,7 @@ function _iconjugate(ws, N) {
522
return ws;
523
}
524
525
-function _inormalize(ws, N) {
526
+function _inormalize13(ws, N) {
527
var carry = 0;
528
for (var i = 0; i < N / 2; ++i) {
529
530
@@ -1051,8 +1111,11 @@ function _inormalize(ws, N) {
531
// assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");
532
//}
533
534
-
535
//assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)
536
+ //
537
+ //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)
538
+ // + Math.round(ws[2 * i].r / N)
539
+ // + carry;
540
541
var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)
542
+ Math.round(ws[2 * i].r / N)
543
@@ -1076,7 +1139,170 @@ function _inormalize(ws, N) {
544
return ws;
545
}
546
547
-function _iconvertToC(ws, N) {
548
+function _inormalize20(ws, N) {
549
+
550
+ var carry = 0;
551
+ var seek = 0;
552
+
553
+ for (var j = 0; j < N; ++j) {
554
+ ws[j] = Math.round(ws[j].r / N);
555
+ }
556
+
557
+ for (var i = 0; i < N; ++i) {
558
+ //var w = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)
559
+ // + ((ws[2 * i].r / N + .5) >> 0)
560
+ // + carry;
561
+
562
+ //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {
563
+ // console.log(1 << 13, 1 * 0x2000);
564
+ // 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));
565
+ // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");
566
+ //}
567
+
568
+ //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)
569
+
570
+ //var w = ws[i];
571
+ //
572
+ //assert(w < (0x4000000 * 0x4000000))
573
+ //
574
+ //console.log("Before ", w, w & 0x3ffffff, carry);
575
+ //
576
+ //if (i + 1 < N) {
577
+ // w += ((ws[i + 1] + 0.5) & 0x3ffffff) * 0x100000;
578
+ //
579
+ // ws[i + 1] &= 0x4000000;
580
+ //}
581
+ //
582
+ //w += carry;
583
+ //
584
+ //ws[i] = w & 0x3ffffff;
585
+ //
586
+ //carry = Math.floor(w / 0x4000000);
587
+ //
588
+ //console.log("After ", w, w & 0x3ffffff, carry);
589
+
590
+ var w = ws[i];
591
+
592
+ //console.log(w, carry, (w & 0x3ffffff));
593
+
594
+ var j = i;
595
+
596
+ //if (w < 0x4000000)
597
+ {
598
+ var pseek = seek;
599
+ seek += 26 - 20;
600
+
601
+ if (seek > 20) {
602
+ if (i < N - 1) {
603
+ w += ws[i + 1] * 0x100000 / (1 << pseek)
604
+
605
+ // !!!
606
+ ++i;
607
+
608
+ seek -= 20;
609
+
610
+ var d = 1 << seek;
611
+
612
+ w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);
613
+ ws[i + 1] /= d;
614
+ }
615
+ }
616
+ else
617
+ {
618
+ var pd = 1 << (pseek);
619
+ var d = 1 << (seek);
620
+
621
+ //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)
622
+
623
+ w += (ws[i + 1] & (d - 1)) * 0x100000 / pd;
624
+ ws[i + 1] /= d;
625
+ }
626
+ }
627
+
628
+ //console.log(w, w & 0x3ffffff, carry)
629
+
630
+ assert(w < 0x4000000 * 0x4000000)
631
+ assert(carry < 0x4000000 * 0x4000000)
632
+
633
+ w += carry;
634
+
635
+ //console.log(w, w & 0x3ffffff, carry)
636
+
637
+ ws[j] = w & 0x3ffffff;
638
+
639
+ carry = Math.floor(w / 0x4000000);
640
+ }
641
+
642
+ return ws;
643
+}
644
+
645
+function _inormalize18(ws, N) {
646
+
647
+ var carry = 0;
648
+ var seek = 0;
649
+
650
+ for (var j = 0; j < N; ++j) {
651
+ ws[j] = Math.round(ws[j].r / N);
652
+ }
653
+
654
+ for (var i = 0; i < N; ++i) {
655
+ var w = ws[i];
656
+
657
+ //console.log(w, carry, (w & 0x3ffffff));
658
+
659
+ var j = i;
660
+
661
+ //if (w < 0x4000000)
662
+ {
663
+ var pseek = seek;
664
+ seek += 26 - 18;
665
+
666
+ if (seek > 18) {
667
+ if (i < N - 1) {
668
+ w += ws[i + 1] * 0x40000 / (1 << pseek)
669
+
670
+ // !!!
671
+ ++i;
672
+
673
+ seek -= 18;
674
+
675
+ var d = 1 << seek;
676
+
677
+ w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);
678
+ ws[i + 1] /= d;
679
+ }
680
+ }
681
+ else
682
+ {
683
+ var pd = 1 << (pseek);
684
+ var d = 1 << (seek);
685
+
686
+ //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)
687
+
688
+ w += (ws[i + 1] & (d - 1)) * 0x40000 / pd;
689
+ ws[i + 1] /= d;
690
+ }
691
+ }
692
+
693
+ //console.log(w, w & 0x3ffffff, carry)
694
+
695
+ assert(w < 0x4000000 * 0x4000000)
696
+ assert(carry < 0x4000000 * 0x4000000)
697
+
698
+ w += carry;
699
+
700
+ //console.log(w, w & 0x3ffffff, carry)
701
+
702
+ ws[j] = w & 0x3ffffff;
703
+
704
+ carry = Math.floor(w / 0x4000000);
705
+ }
706
+
707
+ return ws;
708
+}
709
+
710
+
711
+function _iconvertToC13(ws, N) {
712
var cws = new Array(N);
713
for (var i = 0; i < N / 2; i++) {
714
var w = ws[i] || 0;
715
@@ -1087,6 +1313,125 @@ function _iconvertToC(ws, N) {
716
return cws;
717
}
718
719
+function _iconvertToC20(ws, N) {
720
+ var cws = new Array(N);
721
+
722
+ for (var i = 0, j = 0, seek = 20; i < N; ++i) {
723
+ var w = ws[i] || 0;
724
+ var l = 26;
725
+
726
+ while (l > 0) {
727
+ cws[j] = cws[j] || 0;
728
+
729
+ if (seek >= l) {
730
+ cws[j] += w << (20 - seek);
731
+
732
+ seek -= l;
733
+ if (seek === 0) seek = 20;
734
+ l = 0;
735
+ } else {
736
+ cws[j] += (w & ((1 << seek) - 1)) << (20 - seek);
737
+ w /= 1 << seek;
738
+
739
+ ++j;
740
+ l -= seek;
741
+ seek = 20;
742
+ }
743
+ }
744
+ }
745
+
746
+ for (i = 0; i < N; ++i) {
747
+ cws[i] = new Complex(cws[i], 0);
748
+ }
749
+
750
+ return cws;
751
+}
752
+
753
+function _iconvertToC18(ws, N) {
754
+ var cws = new Array(N);
755
+
756
+ for (var i = 0, j = 0, seek = 18; i < N; ++i) {
757
+ var w = ws[i] || 0;
758
+ var l = 26;
759
+
760
+ while (l > 0) {
761
+ cws[j] = cws[j] || 0;
762
+
763
+ if (seek >= l) {
764
+ cws[j] += w << (18 - seek);
765
+
766
+ seek -= l;
767
+ if (seek === 0) seek = 18;
768
+ l = 0;
769
+ } else {
770
+ cws[j] += (w & ((1 << seek) - 1)) << (18 - seek);
771
+ w /= 1 << seek;
772
+
773
+ ++j;
774
+ l -= seek;
775
+ seek = 18;
776
+ }
777
+ }
778
+ }
779
+
780
+ for (i = 0; i < N; ++i) {
781
+ cws[i] = new Complex(cws[i], 0);
782
+ }
783
+
784
+ return cws;
785
+}
786
+
787
+function _iconvertTo13(ws, N) {
788
+ var cws = new Array(N);
789
+ var carry = 0;
790
+
791
+ var i = 0;
792
+ for (i = 0; i < N; ++i) {
793
+ ws[i] = Math.round(ws[i].r / N);
794
+ }
795
+
796
+ i = 0;
797
+ for (var j = 0; true; ++j) {
798
+
799
+ if (carry < 0x2000) {
800
+ if (i === N)
801
+ break;
802
+
803
+ carry += ws[i];
804
+ i++;
805
+ }
806
+
807
+ var lo = carry & 0x1fff; // Here we don't care about overflow, since
808
+ // since overflow may only "screw" (trim) high-order
809
+ // bits, while we're particularly interested in low-order ones
810
+
811
+ //console.log(carry, lo)
812
+
813
+ carry = carry / 0x2000; // Since shift would trigger conversion from
814
+ // float (64) to int (32)
815
+
816
+ cws[j] = lo;
817
+ }
818
+
819
+ //for (var i = 0; i < N; i++) {
820
+ // carry += Math.round(ws[i].r / N);
821
+ //
822
+ //
823
+ // var lo = carry & 0x1fff; // Here we don't care about overflow, since
824
+ // // since overflow may only "screw" (trim) high-order
825
+ // // bits, while we're particularly interested in low-order ones
826
+ //
827
+ // console.log(carry, lo)
828
+ //
829
+ // carry = carry / 0x2000; // Since shift would trigger conversion from
830
+ // // float (64) to int (32)
831
+ //
832
+ // cws[i] = lo;
833
+ //}
834
+
835
+ return cws;
836
+}
837
+
838
BN.prototype.mulTo = function mulTo(num, out) {
839
var res;
840
//if (this.length + num.length < 63)
841
@@ -1111,6 +1456,7 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
842
out.length = this.length + num.length;
843
844
var N = 2 * _guess(this.length, num.length);
845
+ //var N = _guess(this.length * 1.3, num.length * 1.3);
846
847
var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));
848
849
@@ -1123,8 +1469,12 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
850
851
//console.log("A, B: ", this, num);
852
853
- _FFT(_iconvertToC(this.words, N), 0, 0, thisWFT, 0, w, N);
854
- _FFT(_iconvertToC(num.words, N), 0, 0, numWFT, 0, w, N);
855
+ _FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);
856
+ _FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);
857
+ //_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);
858
+ //_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);
859
+ //_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);
860
+ //_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);
861
862
for (var i = 0; i < N; ++i) {
863
//multWFT[i] = thisWFT[i].mul(numWFT[i]);
864
@@ -1138,7 +1488,9 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
865
866
//console.log(multW);
867
868
- multW = _inormalize(_iconjugate(multW, N), N);
869
+ multW = _inormalize13(_iconjugate(multW, N), N);
870
+ //multW = _inormalize20(_iconjugate(multW, N), N);
871
+ //multW = _inormalize18(_iconjugate(multW, N), N);
872
873
out.words = multW;
874
875
diff --git a/test/_fft.js b/test/_fft.js
876
new file mode 100644
877
index 0000000..78c5233
878
--- /dev/null
879
+++ b/test/_fft.js
880
@@ -0,0 +1,43 @@
881
+var BN = require("../lib/bn.js").BN
882
+var fixtures = require("./fixtures.js")
883
+
884
+//var a = new BN("1");
885
+//var b = new BN("1");
886
+
887
+//var a = new BN("123");
888
+//var b = new BN("123");
889
+
890
+//var a = new BN("123456");
891
+//var b = new BN("123456");
892
+
893
+//var a = new BN("12345690");
894
+//var b = new BN("1234560");
895
+
896
+//var a = new BN("123456900");
897
+//var b = new BN("12345601");
898
+
899
+//var a = new BN("123456789");
900
+//var b = new BN("123456780");
901
+
902
+//var a = new BN("123456789");
903
+//var b = new BN("123456789");
904
+
905
+//var a = new BN(
906
+// '13f29a3e0bc10e100ce0', 16);
907
+//var b = a.clone();
908
+
909
+
910
+var a = new BN(fixtures.dhGroups.p17.q, 16);
911
+var b = a.clone();
912
+var qs = fixtures.dhGroups.p17.qs;
913
+
914
+var c = a.mulf(b);
915
+var c_ = a.mul(b);
916
+
917
+//console.log(c.words);
918
+console.log(c);
919
+console.log("------")
920
+//console.log(c_.words);
921
+console.log(c_);
922
+
923
+//assert(c === new BN(2))
924
925
From 47297ab0ccfc9e66b37dd53a86b7fcb09c17db63 Mon Sep 17 00:00:00 2001
926
From: Alexey Kudinkin <[email protected]>
927
Date: Sun, 14 Dec 2014 19:51:28 +0300
928
Subject: [PATCH 03/12] Unrolled recursion
929
930
---
931
lib/bn.js | 141 +++++++++++++++++++++++++++++++++++------------------------
932
test/_fft.js | 10 ++++-
933
2 files changed, 93 insertions(+), 58 deletions(-)
934
935
diff --git a/lib/bn.js b/lib/bn.js
936
index c803573..d173a6d 100644
937
--- a/lib/bn.js
938
+++ b/lib/bn.js
939
@@ -1003,8 +1003,8 @@ function _FFT(ws, p, s, tws, tp, r, N) {
940
941
//console.log(tws);
942
943
- assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))
944
- assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))
945
+ //assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))
946
+ //assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))
947
948
r_.imul(r);
949
950
@@ -1013,73 +1013,98 @@ function _FFT(ws, p, s, tws, tp, r, N) {
951
}
952
}
953
954
+var π = 3.14159265359;
955
956
-function _FFTL(ws, p, s, tws, tp, r, N) {
957
- //if (N === 1) {
958
- // tws[tp] = ws[p];
959
- // //console.log("p/tp/ws/tws :", p, tp, ws, tws);
960
- //} else {
961
- // var hN = N / 2 >> 0;
962
- //
963
- // var rr = r.mul(r);
964
- //
965
- // var s_ = 2 * s + 1;
966
- //
967
- // //console.log("-- FFT -- # ", N);
968
- // //console.log("-- R -- ", r);
969
- //
970
- // //console.log("-- RR -- # ", rr);
971
- //
972
- // _FFT(ws, p, s_, tws, tp, rr, hN); // even
973
- // _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd
974
- //
975
- // var r_ = r.clone();
976
- //
977
- // for (var i = 0; i < hN; ++i) {
978
- // var e = tws[tp + i];
979
- // var o = tws[tp + i + hN].clone();
980
- //
981
- // //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)
982
- // //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));
983
- //
984
- // o.imul(r_);
985
- //
986
- // tws[tp + i] = e.add(o);
987
- // tws[tp + i + hN] = e.sub(o);
988
- //
989
- // r_.imul(r);
990
- //
991
- // //console.log("tws | ", tws)
992
- // }
993
+
994
+function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {
995
+ //var hN = N / 2 >> 0;
996
+
997
+ //for (var j = 0; j < 2; ++j)
998
+ //for (var i = 0, hhN = hN >> 1, dN = hN; i < hhN; ++i, dN >>= 1) {
999
+ // tws[2 * i] = ws[dN + j];
1000
+ // tws[2 * i + 1] = ws[dN + j + ];
1001
//}
1002
1003
- var hN = N / 2 >> 0;
1004
+ //console.log("XXXXX")
1005
+ //console.log("WS, TWS", ws, tws)
1006
1007
- for (var i = 0; i < hN; i++) {
1008
- tws[2 * i] = ws[i];
1009
- tws[2 * i + 1] = ws[i + hN];
1010
- }
1011
+ _permuteTo(rbt, ws, tws, N);
1012
+
1013
+ var hN = N >>> 1;
1014
+
1015
+ for (var s = 1; s < N; s <<= 1) {
1016
+ var l = s << 1;
1017
+ var r = new Complex(Math.cos(2 * π / l), Math.sin(2 * π / l));
1018
+
1019
+ for (var p = 0; p < N; p += l) {
1020
+ var r_ = r.clone();
1021
+
1022
+ for (var j = 0; j < s; ++j) {
1023
+ var e = tws[p + j];
1024
+ var o = tws[p + j + s].clone();
1025
+
1026
+ o.imul(r_);
1027
1028
- var p = 0;
1029
+ tws[p + j] = e.add(o);
1030
+ tws[p + j + s] = e.sub(o)
1031
1032
- for (var l = 1; l < N + 1; l << 1, p = 0) {
1033
- for (var j = p; j < p + l; ++j, p += l) {
1034
- var e = tws[j];
1035
- var o = tws[j + l].clone();
1036
+ //assert(tws[p + j].r < (0x4000000 * 0x4000000 * 2))
1037
+ //assert(tws[p + j + s].r < (0x4000000 * 0x4000000 * 2))
1038
+
1039
+ if (j !== l) r_.imul(r);
1040
+ }
1041
}
1042
+
1043
+ //console.log(tws)
1044
}
1045
}
1046
1047
-var π = 3.14159265359;
1048
+function _makeRBT(N) {
1049
+ var t = new Array(N);
1050
+ var l = (Math.log(N) / Math.log(2)) >> 0;
1051
+ for (var i = 0; i < N; ++i) {
1052
+ t[i] = _revbin(i, l, N);
1053
+ }
1054
+
1055
+ return t;
1056
+}
1057
+
1058
+function _permuteTo(rbt, ws, tws, N) {
1059
+ //var l = (Math.log(N) / Math.log(2)) >> 0;
1060
+ for (var i = 0; i < N; ++i) {
1061
+ //var r = _revbin(i, l, N);
1062
+ //console.log("REVBIN: ", i, r)
1063
+ //if (r > i) {
1064
+ // var t = ws[i];
1065
+ // ws[i] = ws[r];
1066
+ // ws[r] = t;
1067
+ //}
1068
+ tws[i] = ws[rbt[i]];
1069
+ }
1070
+}
1071
+
1072
+function _revbin(x, l, N) {
1073
+ if (x === 0 || x === N - 1)
1074
+ return x;
1075
+
1076
+ var rb = 0;
1077
+ for (var i = 0; i < l; ++i) {
1078
+ rb |= (x & 1) << (l - i - 1);
1079
+ x >>= 1;
1080
+ }
1081
+
1082
+ return rb;
1083
+}
1084
+
1085
1086
function _guess(n, m) {
1087
- var N = (n < m ? n : m) | 1, odd = N & 1;
1088
+ var N = Math.max(m, n) | 1, odd = N & 1;
1089
var i = 0;
1090
- for (; N; N = N / 2 >> 0) {
1091
+ while (N = N / 2 >> 0) {
1092
i++;
1093
}
1094
1095
- return (1 << i + odd)
1096
+ return (1 << i + 1 + odd)
1097
}
1098
1099
function _iconjugate(ws, N) {
1100
@@ -1469,8 +1494,12 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1101
1102
//console.log("A, B: ", this, num);
1103
1104
- _FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);
1105
- _FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);
1106
+ var rbt = _makeRBT(N);
1107
+
1108
+ //_FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);
1109
+ //_FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);
1110
+ _FFTL(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N, rbt);
1111
+ _FFTL(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N, rbt);
1112
//_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);
1113
//_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);
1114
//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);
1115
@@ -1484,7 +1513,7 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1116
//console.log("-- MULF -- ", multWFT);
1117
1118
//_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);
1119
- _FFT(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N);
1120
+ _FFTL(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N, rbt);
1121
1122
//console.log(multW);
1123
1124
diff --git a/test/_fft.js b/test/_fft.js
1125
index 78c5233..40237ed 100644
1126
--- a/test/_fft.js
1127
+++ b/test/_fft.js
1128
@@ -4,9 +4,15 @@ var fixtures = require("./fixtures.js")
1129
//var a = new BN("1");
1130
//var b = new BN("1");
1131
1132
+//var a = new BN("2");
1133
+//var b = new BN("13");
1134
+
1135
//var a = new BN("123");
1136
//var b = new BN("123");
1137
1138
+//var a = new BN("12345");
1139
+//var b = new BN("1");
1140
+
1141
//var a = new BN("123456");
1142
//var b = new BN("123456");
1143
1144
@@ -16,8 +22,8 @@ var fixtures = require("./fixtures.js")
1145
//var a = new BN("123456900");
1146
//var b = new BN("12345601");
1147
1148
-//var a = new BN("123456789");
1149
-//var b = new BN("123456780");
1150
+//var a = new BN("0x2000", 16);
1151
+//var b = new BN("12345678");
1152
1153
//var a = new BN("123456789");
1154
//var b = new BN("123456789");
1155
1156
From c5570b41d7b8b4b72439ea4a5e1100b715b55d2e Mon Sep 17 00:00:00 2001
1157
From: Alexey Kudinkin <[email protected]>
1158
Date: Sun, 14 Dec 2014 21:04:28 +0300
1159
Subject: [PATCH 04/12] Remastered FFT to purge any object creation (except
1160
arrays)
1161
1162
---
1163
lib/bn.js | 299 ++++++++++++++++++++++++++++++++++++++++++++++----------------
1164
1 file changed, 221 insertions(+), 78 deletions(-)
1165
1166
diff --git a/lib/bn.js b/lib/bn.js
1167
index d173a6d..460a3bd 100644
1168
--- a/lib/bn.js
1169
+++ b/lib/bn.js
1170
@@ -1016,7 +1016,7 @@ function _FFT(ws, p, s, tws, tp, r, N) {
1171
var π = 3.14159265359;
1172
1173
1174
-function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {
1175
+function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {
1176
//var hN = N / 2 >> 0;
1177
1178
//for (var j = 0; j < 2; ++j)
1179
@@ -1028,30 +1028,57 @@ function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {
1180
//console.log("XXXXX")
1181
//console.log("WS, TWS", ws, tws)
1182
1183
- _permuteTo(rbt, ws, tws, N);
1184
-
1185
- var hN = N >>> 1;
1186
+ _permuteTo(rbt, rws, iws, rtws, itws, N);
1187
1188
for (var s = 1; s < N; s <<= 1) {
1189
var l = s << 1;
1190
- var r = new Complex(Math.cos(2 * π / l), Math.sin(2 * π / l));
1191
+
1192
+ var rtwdf = Math.cos(2 * π / l);
1193
+ var itwdf = Math.sin(2 * π / l);
1194
1195
for (var p = 0; p < N; p += l) {
1196
- var r_ = r.clone();
1197
+ var rtwdf_ = rtwdf;
1198
+ var itwdf_ = itwdf;
1199
1200
for (var j = 0; j < s; ++j) {
1201
- var e = tws[p + j];
1202
- var o = tws[p + j + s].clone();
1203
1204
- o.imul(r_);
1205
+ //var e = tws[p + j];
1206
+
1207
+ var re = rtws[p + j];
1208
+ var ie = itws[p + j];
1209
+
1210
+ //var o = tws[p + j + s].clone();
1211
+
1212
+ var ro = rtws[p + j + s];
1213
+ var io = itws[p + j + s];
1214
+
1215
+ //o.imul(r_);
1216
+
1217
+ var rx = rtwdf_ * ro - itwdf_ * io;
1218
+
1219
+ io = rtwdf_ * io + itwdf_ * ro;
1220
+ ro = rx;
1221
1222
- tws[p + j] = e.add(o);
1223
- tws[p + j + s] = e.sub(o)
1224
+ //tws[p + j] = e.add(o);
1225
+
1226
+ rtws[p + j] = re + ro;
1227
+ itws[p + j] = ie + io;
1228
+
1229
+ //tws[p + j + s] = e.sub(o)
1230
+
1231
+ rtws[p + j + s] = re - ro;
1232
+ itws[p + j + s] = ie - io;
1233
1234
//assert(tws[p + j].r < (0x4000000 * 0x4000000 * 2))
1235
//assert(tws[p + j + s].r < (0x4000000 * 0x4000000 * 2))
1236
1237
- if (j !== l) r_.imul(r);
1238
+ if (j !== l) {
1239
+ //r_.imul(r);
1240
+ var rx = rtwdf * rtwdf_ - itwdf * itwdf_;
1241
+
1242
+ itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
1243
+ rtwdf_ = rx;
1244
+ }
1245
}
1246
}
1247
1248
@@ -1060,7 +1087,7 @@ function _FFTL(ws, _, __, tws, ___, ____, N, rbt) {
1249
}
1250
1251
function _makeRBT(N) {
1252
- var t = new Array(N);
1253
+ var t = new Int32Array(N);
1254
var l = (Math.log(N) / Math.log(2)) >> 0;
1255
for (var i = 0; i < N; ++i) {
1256
t[i] = _revbin(i, l, N);
1257
@@ -1069,7 +1096,7 @@ function _makeRBT(N) {
1258
return t;
1259
}
1260
1261
-function _permuteTo(rbt, ws, tws, N) {
1262
+function _permuteTo(rbt, rws, iws, rtws, itws, N) {
1263
//var l = (Math.log(N) / Math.log(2)) >> 0;
1264
for (var i = 0; i < N; ++i) {
1265
//var r = _revbin(i, l, N);
1266
@@ -1079,7 +1106,8 @@ function _permuteTo(rbt, ws, tws, N) {
1267
// ws[i] = ws[r];
1268
// ws[r] = t;
1269
//}
1270
- tws[i] = ws[rbt[i]];
1271
+ rtws[i] = rws[rbt[i]];
1272
+ itws[i] = iws[rbt[i]];
1273
}
1274
}
1275
1276
@@ -1122,6 +1150,22 @@ function _iconjugate(ws, N) {
1277
return ws;
1278
}
1279
1280
+function _iconjugateX(rws, iws, N) {
1281
+ if (N > 1) {
1282
+ for (var i = 0; i < N / 2; ++i) {
1283
+ var t = rws[i];
1284
+
1285
+ rws[i] = rws[N - i - 1];
1286
+ rws[N - i - 1] = t;
1287
+
1288
+ t = iws[i];
1289
+
1290
+ iws[i] = -iws[N - i - 1];
1291
+ iws[N - i - 1] = -t;
1292
+ }
1293
+ }
1294
+}
1295
+
1296
function _inormalize13(ws, N) {
1297
var carry = 0;
1298
for (var i = 0; i < N / 2; ++i) {
1299
@@ -1164,6 +1208,49 @@ function _inormalize13(ws, N) {
1300
return ws;
1301
}
1302
1303
+
1304
+function _inormalize13X(ws, N) {
1305
+ var carry = 0;
1306
+ for (var i = 0; i < N / 2; ++i) {
1307
+
1308
+ //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)
1309
+ // + ((ws[2 * i].r / N + .5) >> 0)
1310
+ // + carry;
1311
+
1312
+ //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {
1313
+ // console.log(1 << 13, 1 * 0x2000);
1314
+ // 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));
1315
+ // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");
1316
+ //}
1317
+
1318
+ //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)
1319
+ //
1320
+ //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)
1321
+ // + Math.round(ws[2 * i].r / N)
1322
+ // + carry;
1323
+
1324
+ var n = (Math.round(ws[2 * i + 1] / N) * 0x2000)
1325
+ + Math.round(ws[2 * i] / N)
1326
+ + carry;
1327
+
1328
+ //console.log(
1329
+ // n.toString(16),
1330
+ // carry.toString(16),
1331
+ // (n & 0x3ffffff).toString(16)
1332
+ // );
1333
+
1334
+ ws[i] = n & 0x3ffffff;
1335
+
1336
+ if (n < 0x4000000) {
1337
+ carry = 0;
1338
+ } else {
1339
+ carry = Math.floor(n / 0x4000000);
1340
+ }
1341
+ }
1342
+
1343
+ return ws;
1344
+}
1345
+
1346
function _inormalize20(ws, N) {
1347
1348
var carry = 0;
1349
@@ -1338,6 +1425,18 @@ function _iconvertToC13(ws, N) {
1350
return cws;
1351
}
1352
1353
+function _iconvertTo13(ws, rws, iws, N) {
1354
+ for (var i = 0; i < N / 2; i++) {
1355
+ var w = ws[i] | 0;
1356
+
1357
+ rws[2 * i] = w & 0x1fff;
1358
+ iws[2 * i] = 0;
1359
+
1360
+ rws[2 * i + 1] = w >>> 13;
1361
+ iws[2 * i + 1] = 0;
1362
+ }
1363
+}
1364
+
1365
function _iconvertToC20(ws, N) {
1366
var cws = new Array(N);
1367
1368
@@ -1406,56 +1505,56 @@ function _iconvertToC18(ws, N) {
1369
return cws;
1370
}
1371
1372
-function _iconvertTo13(ws, N) {
1373
- var cws = new Array(N);
1374
- var carry = 0;
1375
-
1376
- var i = 0;
1377
- for (i = 0; i < N; ++i) {
1378
- ws[i] = Math.round(ws[i].r / N);
1379
- }
1380
-
1381
- i = 0;
1382
- for (var j = 0; true; ++j) {
1383
-
1384
- if (carry < 0x2000) {
1385
- if (i === N)
1386
- break;
1387
-
1388
- carry += ws[i];
1389
- i++;
1390
- }
1391
-
1392
- var lo = carry & 0x1fff; // Here we don't care about overflow, since
1393
- // since overflow may only "screw" (trim) high-order
1394
- // bits, while we're particularly interested in low-order ones
1395
-
1396
- //console.log(carry, lo)
1397
-
1398
- carry = carry / 0x2000; // Since shift would trigger conversion from
1399
- // float (64) to int (32)
1400
-
1401
- cws[j] = lo;
1402
- }
1403
-
1404
- //for (var i = 0; i < N; i++) {
1405
- // carry += Math.round(ws[i].r / N);
1406
- //
1407
- //
1408
- // var lo = carry & 0x1fff; // Here we don't care about overflow, since
1409
- // // since overflow may only "screw" (trim) high-order
1410
- // // bits, while we're particularly interested in low-order ones
1411
- //
1412
- // console.log(carry, lo)
1413
- //
1414
- // carry = carry / 0x2000; // Since shift would trigger conversion from
1415
- // // float (64) to int (32)
1416
- //
1417
- // cws[i] = lo;
1418
- //}
1419
-
1420
- return cws;
1421
-}
1422
+//function _iconvertTo13(ws, N) {
1423
+// var cws = new Array(N);
1424
+// var carry = 0;
1425
+//
1426
+// var i = 0;
1427
+// for (i = 0; i < N; ++i) {
1428
+// ws[i] = Math.round(ws[i].r / N);
1429
+// }
1430
+//
1431
+// i = 0;
1432
+// for (var j = 0; true; ++j) {
1433
+//
1434
+// if (carry < 0x2000) {
1435
+// if (i === N)
1436
+// break;
1437
+//
1438
+// carry += ws[i];
1439
+// i++;
1440
+// }
1441
+//
1442
+// var lo = carry & 0x1fff; // Here we don't care about overflow, since
1443
+// // since overflow may only "screw" (trim) high-order
1444
+// // bits, while we're particularly interested in low-order ones
1445
+//
1446
+// //console.log(carry, lo)
1447
+//
1448
+// carry = carry / 0x2000; // Since shift would trigger conversion from
1449
+// // float (64) to int (32)
1450
+//
1451
+// cws[j] = lo;
1452
+// }
1453
+//
1454
+// //for (var i = 0; i < N; i++) {
1455
+// // carry += Math.round(ws[i].r / N);
1456
+// //
1457
+// //
1458
+// // var lo = carry & 0x1fff; // Here we don't care about overflow, since
1459
+// // // since overflow may only "screw" (trim) high-order
1460
+// // // bits, while we're particularly interested in low-order ones
1461
+// //
1462
+// // console.log(carry, lo)
1463
+// //
1464
+// // carry = carry / 0x2000; // Since shift would trigger conversion from
1465
+// // // float (64) to int (32)
1466
+// //
1467
+// // cws[i] = lo;
1468
+// //}
1469
+//
1470
+// return cws;
1471
+//}
1472
1473
BN.prototype.mulTo = function mulTo(num, out) {
1474
var res;
1475
@@ -1483,14 +1582,14 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1476
var N = 2 * _guess(this.length, num.length);
1477
//var N = _guess(this.length * 1.3, num.length * 1.3);
1478
1479
- var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));
1480
+ //var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));
1481
1482
//console.log("-- W -- ", w);
1483
1484
- var thisWFT = new Array(N),
1485
- numWFT = new Array(N),
1486
- //multWFT = new Array(N),
1487
- multW = new Array(N);
1488
+ //var thisWFT = new Array(N),
1489
+ // numWFT = new Array(N),
1490
+ // //multWFT = new Array(N),
1491
+ // multW = new Array(N);
1492
1493
//console.log("A, B: ", this, num);
1494
1495
@@ -1498,36 +1597,80 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1496
1497
//_FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);
1498
//_FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);
1499
- _FFTL(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N, rbt);
1500
- _FFTL(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N, rbt);
1501
//_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);
1502
//_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);
1503
//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);
1504
//_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);
1505
1506
+ var rThisWs = new Array(N),
1507
+ iThisWs = new Array(N),
1508
+ rThisWsT = new Array(N), // T for Transformed
1509
+ iThisWsT = new Array(N),
1510
+
1511
+ rNumWs = new Array(N),
1512
+ iNumWs = new Array(N),
1513
+ rNumWsT = new Array(N),
1514
+ iNumWsT = new Array(N),
1515
+
1516
+ rMultWs = new Array(N),
1517
+ iMultWs = new Array(N);
1518
+
1519
+ _iconvertTo13(this.words, rThisWs, iThisWs, N);
1520
+ _iconvertTo13(num.words, rNumWs, iNumWs, N);
1521
+
1522
+ _FFTL(rThisWs, iThisWs, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);
1523
+
1524
+ //console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))
1525
+ //console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))
1526
+
1527
+ _FFTL(rNumWs, iNumWs, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);
1528
+
1529
+ //console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))
1530
+ //console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))
1531
+
1532
for (var i = 0; i < N; ++i) {
1533
- //multWFT[i] = thisWFT[i].mul(numWFT[i]);
1534
- thisWFT[i].imul(numWFT[i]);
1535
+ //thisWFT[i].imul(numWFT[i]);
1536
+ var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];
1537
+
1538
+ iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]
1539
+ rThisWsT[i] = rx;
1540
}
1541
1542
+ //console.log("X * Y[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))
1543
+
1544
//console.log("-- MULF -- ", multWFT);
1545
1546
//_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);
1547
- _FFTL(_iconjugate(thisWFT, N), 0, 0, multW, 0, w, N, rbt);
1548
1549
- //console.log(multW);
1550
+ _iconjugateX(rThisWsT, iThisWsT, N);
1551
+
1552
+ //console.log("X * Y[R/I] Transformed Conjugated", _toArray(rThisWsT), _toArray(iThisWsT))
1553
+
1554
+ _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, iMultWs, 0, 0, N, rbt);
1555
+
1556
+ //console.log("X * Y[R/I] Inverse FFT", _toArray(rMultWs), _toArray(iMultWs))
1557
+
1558
+ _iconjugateX(rMultWs, iMultWs, N);
1559
+
1560
+ _inormalize13X(rMultWs, N);
1561
+
1562
+ //console.log("X * Y[R/I] Conjugated Normalized", _toArray(rMultWs), _toArray(iMultWs))
1563
1564
- multW = _inormalize13(_iconjugate(multW, N), N);
1565
//multW = _inormalize20(_iconjugate(multW, N), N);
1566
//multW = _inormalize18(_iconjugate(multW, N), N);
1567
1568
- out.words = multW;
1569
+ out.words = _toArray(rMultWs);
1570
1571
//console.log("-- MUL -- ", multW);
1572
1573
return out.strip();
1574
};
1575
1576
+function _toArray(f64a) {
1577
+ return [].slice.call(f64a);
1578
+}
1579
+
1580
+
1581
// Multiply `this` by `num`
1582
BN.prototype.mul = function mul(num) {
1583
var out = new BN(null);
1584
1585
From 6dde038bb6100b4aa972c1ab22825dfefbfa1a3e Mon Sep 17 00:00:00 2001
1586
From: Alexey Kudinkin <[email protected]>
1587
Date: Sun, 14 Dec 2014 22:23:59 +0300
1588
Subject: [PATCH 05/12] Vanished some more absurd
1589
1590
---
1591
lib/bn.js | 39 +++++++++++++++++----------------------
1592
1 file changed, 17 insertions(+), 22 deletions(-)
1593
1594
diff --git a/lib/bn.js b/lib/bn.js
1595
index 460a3bd..36beb6d 100644
1596
--- a/lib/bn.js
1597
+++ b/lib/bn.js
1598
@@ -1087,7 +1087,7 @@ function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {
1599
}
1600
1601
function _makeRBT(N) {
1602
- var t = new Int32Array(N);
1603
+ var t = new Array(N);
1604
var l = (Math.log(N) / Math.log(2)) >> 0;
1605
for (var i = 0; i < N; ++i) {
1606
t[i] = _revbin(i, l, N);
1607
@@ -1125,7 +1125,7 @@ function _revbin(x, l, N) {
1608
}
1609
1610
1611
-function _guess(n, m) {
1612
+function _guess13(n, m) {
1613
var N = Math.max(m, n) | 1, odd = N & 1;
1614
var i = 0;
1615
while (N = N / 2 >> 0) {
1616
@@ -1425,15 +1425,12 @@ function _iconvertToC13(ws, N) {
1617
return cws;
1618
}
1619
1620
-function _iconvertTo13(ws, rws, iws, N) {
1621
+function _iconvertTo13(ws, rws, N) {
1622
for (var i = 0; i < N / 2; i++) {
1623
var w = ws[i] | 0;
1624
1625
- rws[2 * i] = w & 0x1fff;
1626
- iws[2 * i] = 0;
1627
-
1628
- rws[2 * i + 1] = w >>> 13;
1629
- iws[2 * i + 1] = 0;
1630
+ rws[2 * i] = w & 0x1fff;
1631
+ rws[2 * i + 1] = w >>> 13;
1632
}
1633
}
1634
1635
@@ -1579,8 +1576,8 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1636
out.sign = num.sign !== this.sign;
1637
out.length = this.length + num.length;
1638
1639
- var N = 2 * _guess(this.length, num.length);
1640
- //var N = _guess(this.length * 1.3, num.length * 1.3);
1641
+ var N = 2 * _guess13(this.length, num.length);
1642
+ //var N = _guess13(this.length * 1.3, num.length * 1.3);
1643
1644
//var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));
1645
1646
@@ -1602,28 +1599,30 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1647
//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);
1648
//_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);
1649
1650
- var rThisWs = new Array(N),
1651
- iThisWs = new Array(N),
1652
+ var zeroes = new Array(N),
1653
+ rThisWs = new Array(N),
1654
rThisWsT = new Array(N), // T for Transformed
1655
iThisWsT = new Array(N),
1656
1657
rNumWs = new Array(N),
1658
- iNumWs = new Array(N),
1659
rNumWsT = new Array(N),
1660
iNumWsT = new Array(N),
1661
1662
rMultWs = new Array(N),
1663
iMultWs = new Array(N);
1664
1665
- _iconvertTo13(this.words, rThisWs, iThisWs, N);
1666
- _iconvertTo13(num.words, rNumWs, iNumWs, N);
1667
+ for (var i = 0; i < N; ++i)
1668
+ zeroes[i] = 0;
1669
+
1670
+ _iconvertTo13(this.words, rThisWs, N);
1671
+ _iconvertTo13(num.words, rNumWs, N);
1672
1673
- _FFTL(rThisWs, iThisWs, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);
1674
+ _FFTL(rThisWs, zeroes, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);
1675
1676
//console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))
1677
//console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))
1678
1679
- _FFTL(rNumWs, iNumWs, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);
1680
+ _FFTL(rNumWs, zeroes, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);
1681
1682
//console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))
1683
//console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))
1684
@@ -1659,17 +1658,13 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1685
//multW = _inormalize20(_iconjugate(multW, N), N);
1686
//multW = _inormalize18(_iconjugate(multW, N), N);
1687
1688
- out.words = _toArray(rMultWs);
1689
+ out.words = rMultWs;
1690
1691
//console.log("-- MUL -- ", multW);
1692
1693
return out.strip();
1694
};
1695
1696
-function _toArray(f64a) {
1697
- return [].slice.call(f64a);
1698
-}
1699
-
1700
1701
// Multiply `this` by `num`
1702
BN.prototype.mul = function mul(num) {
1703
1704
From 4af09f26ad1d4904496d9b92e1b207971ca6d819 Mon Sep 17 00:00:00 2001
1705
From: Alexey Kudinkin <[email protected]>
1706
Date: Sun, 14 Dec 2014 22:43:01 +0300
1707
Subject: [PATCH 06/12] Vapourized yet another array
1708
1709
---
1710
lib/bn.js | 26 ++++++++++++++++----------
1711
1 file changed, 16 insertions(+), 10 deletions(-)
1712
1713
diff --git a/lib/bn.js b/lib/bn.js
1714
index 36beb6d..60953fc 100644
1715
--- a/lib/bn.js
1716
+++ b/lib/bn.js
1717
@@ -1572,6 +1572,7 @@ BN.prototype.mulToF = function mulToF(num, out) {
1718
return res;
1719
};
1720
1721
+
1722
BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1723
out.sign = num.sign !== this.sign;
1724
out.length = this.length + num.length;
1725
@@ -1599,7 +1600,8 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1726
//_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);
1727
//_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);
1728
1729
- var zeroes = new Array(N),
1730
+ var ph = _makePlaceHolderA(N),
1731
+
1732
rThisWs = new Array(N),
1733
rThisWsT = new Array(N), // T for Transformed
1734
iThisWsT = new Array(N),
1735
@@ -1608,21 +1610,17 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1736
rNumWsT = new Array(N),
1737
iNumWsT = new Array(N),
1738
1739
- rMultWs = new Array(N),
1740
- iMultWs = new Array(N);
1741
-
1742
- for (var i = 0; i < N; ++i)
1743
- zeroes[i] = 0;
1744
+ rMultWs = new Array(N);
1745
1746
_iconvertTo13(this.words, rThisWs, N);
1747
_iconvertTo13(num.words, rNumWs, N);
1748
1749
- _FFTL(rThisWs, zeroes, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);
1750
+ _FFTL(rThisWs, ph, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);
1751
1752
//console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))
1753
//console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))
1754
1755
- _FFTL(rNumWs, zeroes, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);
1756
+ _FFTL(rNumWs, ph, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);
1757
1758
//console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))
1759
//console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))
1760
@@ -1645,11 +1643,11 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1761
1762
//console.log("X * Y[R/I] Transformed Conjugated", _toArray(rThisWsT), _toArray(iThisWsT))
1763
1764
- _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, iMultWs, 0, 0, N, rbt);
1765
+ _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, ph, 0, 0, N, rbt);
1766
1767
//console.log("X * Y[R/I] Inverse FFT", _toArray(rMultWs), _toArray(iMultWs))
1768
1769
- _iconjugateX(rMultWs, iMultWs, N);
1770
+ _iconjugateX(rMultWs, ph, N);
1771
1772
_inormalize13X(rMultWs, N);
1773
1774
@@ -1665,6 +1663,14 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
1775
return out.strip();
1776
};
1777
1778
+function _makePlaceHolderA(N) {
1779
+ var ph = new Array(N);
1780
+ for (var i = 0; i < N; ++i)
1781
+ ph[i] = 0;
1782
+
1783
+ return ph;
1784
+}
1785
+
1786
1787
// Multiply `this` by `num`
1788
BN.prototype.mul = function mul(num) {
1789
1790
From 393e6b3d41b4b260de8354937c1061de822aee47 Mon Sep 17 00:00:00 2001
1791
From: Alexey Kudinkin <[email protected]>
1792
Date: Sun, 14 Dec 2014 22:46:07 +0300
1793
Subject: [PATCH 07/12] Cleaned up
1794
1795
---
1796
benchmarks/index.js | 181 +++++++++------
1797
lib/bn.js | 639 +++-------------------------------------------------
1798
test/_fft.js | 49 ----
1799
3 files changed, 143 insertions(+), 726 deletions(-)
1800
delete mode 100644 test/_fft.js
1801
1802
diff --git a/benchmarks/index.js b/benchmarks/index.js
1803
index 64b61d9..75e0f0c 100644
1804
--- a/benchmarks/index.js
1805
+++ b/benchmarks/index.js
1806
@@ -56,90 +56,120 @@ if (/fast/i.test(process.argv[3])) {
1807
benchmark.options.minTime = 1;
1808
}
1809
1810
+var aj = 'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +
1811
+ '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +
1812
+ '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +
1813
+ 'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +
1814
+ 'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +
1815
+ 'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +
1816
+ 'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +
1817
+ 'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +
1818
+ '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +
1819
+ '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +
1820
+ 'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +
1821
+ 'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +
1822
+ '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +
1823
+ 'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +
1824
+ 'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +
1825
+ '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +
1826
+ '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +
1827
+ '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +
1828
+ '100050a430b47bc592995606440272a4994677577a6aaa1b' +
1829
+ 'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +
1830
+ 'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +
1831
+ '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +
1832
+ 'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +
1833
+ '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +
1834
+ '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +
1835
+ '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +
1836
+ '1c64145849b3da8c2d343410df892d958db232617f9896f1' +
1837
+ 'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +
1838
+ 'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +
1839
+ 'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +
1840
+ 'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +
1841
+ '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0';
1842
+
1843
+var bj = '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +
1844
+ '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +
1845
+ 'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +
1846
+ 'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +
1847
+ 'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +
1848
+ 'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +
1849
+ 'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +
1850
+ '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +
1851
+ 'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +
1852
+ '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +
1853
+ '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +
1854
+ '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +
1855
+ 'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +
1856
+ '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +
1857
+ 'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +
1858
+ '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +
1859
+ '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +
1860
+ 'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +
1861
+ 'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +
1862
+ '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +
1863
+ 'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +
1864
+ '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +
1865
+ 'fbedccbc786951025597522eef283e3f56b44561a0765783' +
1866
+ '420128638c257e54b972a76e4261892d81222b3e2039c61a' +
1867
+ 'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +
1868
+ 'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +
1869
+ '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +
1870
+ 'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +
1871
+ 'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +
1872
+ '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +
1873
+ 'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +
1874
+ '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d';
1875
+
1876
+// BN
1877
+
1878
var a1 = new bn('012345678901234567890123456789012345678901234567890', 10);
1879
var b1 = new bn('213509123601923760129376102397651203958123402314875', 10);
1880
1881
-var a1x = new bn( 'a899c59999bf877d96442d284359783bdc64b5f878b688fe' +
1882
- '51407f0526e616553ad0aaaac4d5bed3046f10a1faaf42bb' +
1883
- '2342dc4b7908eea0c46e4c4576897675c2bfdc4467870d3d' +
1884
- 'cd90adaed4359237a4bc6924bfb99aa6bf5f5ede15b574ea' +
1885
- 'e977eac096f3c67d09bda574c6306c6123fa89d2f086b8dc' +
1886
- 'ff92bc570c18d83fe6c810ccfd22ce4c749ef5e6ead3fffe' +
1887
- 'c63d95e0e3fde1df9db6a35fa1d107058f37e41957769199' +
1888
- 'd945dd7a373622c65f0af3fd9eb1ddc5c764bbfaf7a3dc37' +
1889
- '2548e683b970dac4aa4b9869080d2376c9adecebb84e172c' +
1890
- '09aeeb25fb8df23e60033260c4f8aac6b8b98ab894b1fb84' +
1891
- 'ebb83c0fb2081c3f3eee07f44e24d8fabf76f19ed167b0d7' +
1892
- 'ff971565aa4efa3625fce5a43ceeaa3eebb3ce88a00f597f' +
1893
- '048c69292b38dba2103ecdd5ec4ccfe3b2d87fa6202f334b' +
1894
- 'c1cab83b608dfc875b650b69f2c7e23c0b2b4adf149a6100' +
1895
- 'db1b6dbad4679ecb1ea95eafaba3bd00db11c2134f5a8686' +
1896
- '358b8b2ab49a1b2e85e1e45caeac5cd4dc0b3b5fffba8871' +
1897
- '1c6baf399edd48dad5e5c313702737a6dbdcede80ca358e5' +
1898
- '1d1c4fe42e8948a084403f61baed38aa9a1a5ce2918e9f33' +
1899
- '100050a430b47bc592995606440272a4994677577a6aaa1b' +
1900
- 'a101045dbec5a4e9566dab5445d1af3ed19519f07ac4e2a8' +
1901
- 'bd0a84b01978f203a9125a0be020f71fab56c2c9e344d4f4' +
1902
- '12d53d3cd8eb74ca5122002e931e3cb0bd4b7492436be17a' +
1903
- 'd7ebe27148671f59432c36d8c56eb762655711cfc8471f70' +
1904
- '83a8b7283bcb3b1b1d47d37c23d030288cfcef05fbdb4e16' +
1905
- '652ee03ee7b77056a808cd700bc3d9ef826eca9a59be959c' +
1906
- '947c865d6b372a1ca2d503d7df6d7611b12111665438475a' +
1907
- '1c64145849b3da8c2d343410df892d958db232617f9896f1' +
1908
- 'de95b8b5a47132be80dd65298c7f2047858409bf762dbc05' +
1909
- 'a62ca392ac40cfb8201a0607a2cae07d99a307625f2b2d04' +
1910
- 'fe83fbd3ab53602263410f143b73d5b46fc761882e78c782' +
1911
- 'd2c36e716a770a7aefaf7f76cea872db7bffefdbc4c2f9e0' +
1912
- '39c19adac915e7a63dcb8c8c78c113f29a3e0bc10e100ce0', 16);
1913
-
1914
-var b1x = new bn( '3bf836229c7dd874fe37c1790d201e82ed8e192ed61571ca' +
1915
- '7285264974eb2a0171f3747b2fc23969a916cbd21e14f7e2' +
1916
- 'f0d72dcd2247affba926f9e7bb99944cb5609aed85e71b89' +
1917
- 'e89d2651550cb5bd8281bd3144066af78f194032aa777739' +
1918
- 'cccb7862a1af401f99f7e5c693f25ddce2dedd9686633820' +
1919
- 'd28d0f5ed0c6b5a094f5fe6170b8e2cbc9dff118398baee6' +
1920
- 'e895a6301cb6e881b3cae749a5bdf5c56fc897ff68bc73f2' +
1921
- '4811bb108b882872bade1f147d886a415cda2b93dd90190c' +
1922
- 'be5c2dd53fe78add5960e97f58ff2506afe437f4cf4c912a' +
1923
- '397c1a2139ac6207d3ab76e6b7ffd23bb6866dd7f87a9ae5' +
1924
- '578789084ff2d06ea0d30156d7a10496e8ebe094f5703539' +
1925
- '730f5fdbebc066de417be82c99c7da59953071f49da7878d' +
1926
- 'a588775ff2a7f0084de390f009f372af75cdeba292b08ea8' +
1927
- '4bd13a87e1ca678f9ad148145f7cef3620d69a891be46fbb' +
1928
- 'cad858e2401ec0fd72abdea2f643e6d0197b7646fbb83220' +
1929
- '0f4cf7a7f6a7559f9fb0d0f1680822af9dbd8dec4cd1b5e1' +
1930
- '7bc799e902d9fe746ddf41da3b7020350d3600347398999a' +
1931
- 'baf75d53e03ad2ee17de8a2032f1008c6c2e6618b62f225b' +
1932
- 'a2f350179445debe68500fcbb6cae970a9920e321b468b74' +
1933
- '5fb524fb88abbcacdca121d737c44d30724227a99745c209' +
1934
- 'b970d1ff93bbc9f28b01b4e714d6c9cbd9ea032d4e964d8e' +
1935
- '8fff01db095160c20b7646d9fcd314c4bc11bcc232aeccc0' +
1936
- 'fbedccbc786951025597522eef283e3f56b44561a0765783' +
1937
- '420128638c257e54b972a76e4261892d81222b3e2039c61a' +
1938
- 'ab8408fcaac3d634f848ab3ee65ea1bd13c6cd75d2e78060' +
1939
- 'e13cf67fbef8de66d2049e26c0541c679fff3e6afc290efe' +
1940
- '875c213df9678e4a7ec484bc87dae5f0a1c26d7583e38941' +
1941
- 'b7c68b004d4df8b004b666f9448aac1cc3ea21461f41ea5d' +
1942
- 'd0f7a9e6161cfe0f58bcfd304bdc11d78c2e9d542e86c0b5' +
1943
- '6985cc83f693f686eaac17411a8247bf62f5ccc7782349b5' +
1944
- 'cc1f20e312fa2acc0197154d1bfee507e8db77e8f2732f2d' +
1945
- '641440ccf248e8643b2bd1e1f9e8239356ab91098fcb431d', 16);
1946
+var a1j = new bn(aj, 16);
1947
+var b1j = new bn(bj, 16);
1948
+
1949
+// bignum
1950
1951
var a2 = new bignum('012345678901234567890123456789012345678901234567890', 10);
1952
var b2 = new bignum('213509123601923760129376102397651203958123402314875', 10);
1953
1954
+var a2j = new bignum(aj, 16);
1955
+var b2j = new bignum(bj, 16);
1956
+
1957
+// bigi
1958
+
1959
var a4 = new bigi('012345678901234567890123456789012345678901234567890', 10);
1960
var b4 = new bigi('213509123601923760129376102397651203958123402314875', 10);
1961
1962
+var a4j = new bigi(aj, 16);
1963
+var b4j = new bigi(bj, 16);
1964
+
1965
+// sjcl
1966
+
1967
var a5 = new sjcl(a1.toString(16));
1968
var b5 = new sjcl(b1.toString(16));
1969
1970
+var a5j = new sjcl(aj);
1971
+var b5j = new sjcl(bj);
1972
+
1973
+// BigInteger
1974
+
1975
var a6 = new BigInteger('012345678901234567890123456789012345678901234567890', 10);
1976
var b6 = new BigInteger('213509123601923760129376102397651203958123402314875', 10);
1977
1978
+var a6j = new BigInteger(aj, 16);
1979
+var b6j = new BigInteger(bj, 16);
1980
+
1981
+// SilentMattBigInteger
1982
+
1983
var a8 = SilentMattBigInteger.parse('012345678901234567890123456789012345678901234567890', 10);
1984
var b8 = SilentMattBigInteger.parse('213509123601923760129376102397651203958123402314875', 10);
1985
1986
+var a8j = SilentMattBigInteger.parse(aj, 16);
1987
+var b8j = SilentMattBigInteger.parse(aj, 16);
1988
+
1989
var as1 = a1.mul(a1).iaddn(0x2adbeef);
1990
var as2 = a2.mul(a2).add(0x2adbeef);
1991
var as4 = a4.multiply(a4).add(bigi.valueOf(0x2adbeef));
1992
@@ -273,7 +303,7 @@ add('mul', {
1993
},
1994
'bn.js[FFT]': function() {
1995
a1.mulf(b1);
1996
- }
1997
+ },
1998
'bignum': function() {
1999
a2.mul(b2);
2000
},
2001
@@ -293,10 +323,25 @@ add('mul', {
2002
2003
add('mul-jumbo', {
2004
'bn.js': function() {
2005
- a1x.mul(b1x);
2006
+ a1j.mul(b1j);
2007
},
2008
'bn.js[FFT]': function() {
2009
- a1x.mulf(b1x);
2010
+ a1j.mulf(b1j);
2011
+ },
2012
+ 'bignum': function() {
2013
+ a2j.mul(b2j);
2014
+ },
2015
+ 'bigi': function() {
2016
+ a4j.multiply(b4j);
2017
+ },
2018
+ 'sjcl': function() {
2019
+ a5j.mul(b5j);
2020
+ },
2021
+ 'yaffle': function() {
2022
+ a6j.multiply(b6j);
2023
+ },
2024
+ 'silentmatt-biginteger': function() {
2025
+ a8j.multiply(b8j);
2026
}
2027
});
2028
2029
diff --git a/lib/bn.js b/lib/bn.js
2030
index 60953fc..c1aaedd 100644
2031
--- a/lib/bn.js
2032
+++ b/lib/bn.js
2033
@@ -883,151 +883,24 @@ BN.prototype._bigMulTo = function _bigMulTo(num, out) {
2034
return out.strip();
2035
};
2036
2037
+BN.prototype.mulTo = function mulTo(num, out) {
2038
+ var res;
2039
+ var len = this.length + num.length;
2040
+ if (len < 63)
2041
+ res = this._smallMulTo(num, out);
2042
+ else if (len < 1024)
2043
+ res = this._bigMulTo(num, out);
2044
+ else
2045
+ res = this._bigMulToF(num, out);
2046
+ return res;
2047
+};
2048
2049
-function Complex(r, i) {
2050
- this.r = r;
2051
- this.i = i;
2052
-
2053
- //this._norm();
2054
-}
2055
-
2056
-// private
2057
-function _iaddC(rhs) {
2058
- this.r += rhs.r;
2059
- this.i += rhs.i;
2060
-
2061
- //this._norm();
2062
-
2063
- return this;
2064
-}
2065
-
2066
-function _addC(rhs) {
2067
- var t = new Complex(this.r, this.i);
2068
- t.iadd(rhs);
2069
- return t;
2070
-}
2071
-
2072
-function _isubC(rhs) {
2073
- this.r -= rhs.r;
2074
- this.i -= rhs.i
2075
-
2076
- //this._norm();
2077
-
2078
- return this;
2079
-}
2080
-
2081
-function _subC(rhs) {
2082
- var t = new Complex(this.r, this.i);
2083
- t.isub(rhs);
2084
- return t;
2085
-}
2086
-
2087
-function _iconjC() {
2088
- this.i *= -1;
2089
- return this;
2090
-}
2091
-
2092
-function _imulC(rhs) {
2093
- var r = this.r * rhs.r - this.i * rhs.i,
2094
- i = this.r * rhs.i + this.i * rhs.r;
2095
-
2096
- this.r = r;
2097
- this.i = i;
2098
-
2099
- //this._norm();
2100
-
2101
- return this;
2102
-}
2103
-
2104
-function _mulC(rhs) {
2105
- var t = new Complex(this.r, this.i);
2106
- t.imul(rhs);
2107
- return t;
2108
-}
2109
-
2110
-function _cloneC() {
2111
- return new Complex(this.r, this.i);
2112
-}
2113
-
2114
-Complex.prototype.mul = _mulC;
2115
-Complex.prototype.imul = _imulC;
2116
-Complex.prototype.add = _addC;
2117
-Complex.prototype.iadd = _iaddC;
2118
-Complex.prototype.sub = _subC;
2119
-Complex.prototype.isub = _isubC;
2120
-Complex.prototype.iconj = _iconjC;
2121
-Complex.prototype.clone = _cloneC;
2122
-
2123
-//Complex.prototype._isZero = function (v) {
2124
-// return Math.abs(v) < 1.e-12;
2125
-//}
2126
-
2127
-//Complex.prototype._norm = function () {
2128
- //if (this._isZero(this.r)) this.r = 0;
2129
- //if (this._isZero(this.i)) this.i = 0;
2130
-//}
2131
-
2132
-// _FFT(this.words, thisWFT, w, N, 0);
2133
-function _FFT(ws, p, s, tws, tp, r, N) {
2134
- if (N === 1) {
2135
- tws[tp] = ws[p];
2136
- //console.log("p/tp/ws/tws :", p, tp, ws, tws);
2137
- } else {
2138
- var hN = N / 2 >> 0;
2139
-
2140
- var rr = r.mul(r);
2141
-
2142
- var s_ = 2 * s + 1;
2143
-
2144
- //console.log("-- FFT -- # ", N);
2145
- //console.log("-- R -- ", r);
2146
-
2147
- //console.log("-- RR -- # ", rr);
2148
-
2149
- _FFT(ws, p, s_, tws, tp, rr, hN); // even
2150
- _FFT(ws, p + s + 1, s_, tws, tp + hN, rr, hN); // odd
2151
-
2152
- var r_ = r.clone();
2153
-
2154
- for (var i = 0; i < hN; ++i) {
2155
- var e = tws[tp + i];
2156
- var o = tws[tp + i + hN].clone();
2157
-
2158
- //console.log("tp + i, tp + i + hN, tws | ", tp + i, tp + i + hN, tws)
2159
- //console.log("r_, o, e, (o * r_)", r_, o, e, o.mul(r_));
2160
-
2161
- o.imul(r_);
2162
-
2163
- tws[tp + i] = e.add(o);
2164
- tws[tp + i + hN] = e.sub(o);
2165
-
2166
- //console.log(tws);
2167
-
2168
- //assert(tws[tp + i].r < (0x4000000 * 0x4000000 * 2))
2169
- //assert(tws[tp + i + hN].r < (0x4000000 * 0x4000000 * 2))
2170
-
2171
- r_.imul(r);
2172
2173
- //console.log("tws | ", tws)
2174
- }
2175
- }
2176
-}
2177
+// Private
2178
2179
var π = 3.14159265359;
2180
2181
-
2182
-function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {
2183
- //var hN = N / 2 >> 0;
2184
-
2185
- //for (var j = 0; j < 2; ++j)
2186
- //for (var i = 0, hhN = hN >> 1, dN = hN; i < hhN; ++i, dN >>= 1) {
2187
- // tws[2 * i] = ws[dN + j];
2188
- // tws[2 * i + 1] = ws[dN + j + ];
2189
- //}
2190
-
2191
- //console.log("XXXXX")
2192
- //console.log("WS, TWS", ws, tws)
2193
-
2194
+function _FFTL(rws, iws, rtws, itws, N, rbt) {
2195
_permuteTo(rbt, rws, iws, rtws, itws, N);
2196
2197
for (var s = 1; s < N; s <<= 1) {
2198
@@ -1042,38 +915,24 @@ function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {
2199
2200
for (var j = 0; j < s; ++j) {
2201
2202
- //var e = tws[p + j];
2203
-
2204
var re = rtws[p + j];
2205
var ie = itws[p + j];
2206
2207
- //var o = tws[p + j + s].clone();
2208
-
2209
var ro = rtws[p + j + s];
2210
var io = itws[p + j + s];
2211
2212
- //o.imul(r_);
2213
-
2214
var rx = rtwdf_ * ro - itwdf_ * io;
2215
2216
io = rtwdf_ * io + itwdf_ * ro;
2217
ro = rx;
2218
2219
- //tws[p + j] = e.add(o);
2220
-
2221
rtws[p + j] = re + ro;
2222
itws[p + j] = ie + io;
2223
2224
- //tws[p + j + s] = e.sub(o)
2225
-
2226
rtws[p + j + s] = re - ro;
2227
itws[p + j + s] = ie - io;
2228
2229
- //assert(tws[p + j].r < (0x4000000 * 0x4000000 * 2))
2230
- //assert(tws[p + j + s].r < (0x4000000 * 0x4000000 * 2))
2231
-
2232
if (j !== l) {
2233
- //r_.imul(r);
2234
var rx = rtwdf * rtwdf_ - itwdf * itwdf_;
2235
2236
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
2237
@@ -1081,8 +940,6 @@ function _FFTL(rws, iws, _, __, rtws, itws, ___, ____, N, rbt) {
2238
}
2239
}
2240
}
2241
-
2242
- //console.log(tws)
2243
}
2244
}
2245
2246
@@ -1097,15 +954,7 @@ function _makeRBT(N) {
2247
}
2248
2249
function _permuteTo(rbt, rws, iws, rtws, itws, N) {
2250
- //var l = (Math.log(N) / Math.log(2)) >> 0;
2251
for (var i = 0; i < N; ++i) {
2252
- //var r = _revbin(i, l, N);
2253
- //console.log("REVBIN: ", i, r)
2254
- //if (r > i) {
2255
- // var t = ws[i];
2256
- // ws[i] = ws[r];
2257
- // ws[r] = t;
2258
- //}
2259
rtws[i] = rws[rbt[i]];
2260
itws[i] = iws[rbt[i]];
2261
}
2262
@@ -1135,22 +984,7 @@ function _guess13(n, m) {
2263
return (1 << i + 1 + odd)
2264
}
2265
2266
-function _iconjugate(ws, N) {
2267
- if (N > 1) {
2268
- for (var i = 0; i < N / 2; ++i) {
2269
- var t = ws[i];
2270
- ws[i] = ws[N - i - 1];
2271
- ws[N - i - 1] = t;
2272
-
2273
- ws[i].i *= -1;
2274
- ws[N - i - 1].i *= -1;
2275
- }
2276
- }
2277
-
2278
- return ws;
2279
-}
2280
-
2281
-function _iconjugateX(rws, iws, N) {
2282
+function _iconjugate(rws, iws, N) {
2283
if (N > 1) {
2284
for (var i = 0; i < N / 2; ++i) {
2285
var t = rws[i];
2286
@@ -1169,262 +1003,22 @@ function _iconjugateX(rws, iws, N) {
2287
function _inormalize13(ws, N) {
2288
var carry = 0;
2289
for (var i = 0; i < N / 2; ++i) {
2290
-
2291
- //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)
2292
- // + ((ws[2 * i].r / N + .5) >> 0)
2293
- // + carry;
2294
-
2295
- //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {
2296
- // console.log(1 << 13, 1 * 0x2000);
2297
- // 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));
2298
- // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");
2299
- //}
2300
-
2301
- //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)
2302
- //
2303
- //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)
2304
- // + Math.round(ws[2 * i].r / N)
2305
- // + carry;
2306
-
2307
- var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)
2308
- + Math.round(ws[2 * i].r / N)
2309
- + carry;
2310
-
2311
- //console.log(
2312
- // n.toString(16),
2313
- // carry.toString(16),
2314
- // (n & 0x3ffffff).toString(16)
2315
- // );
2316
-
2317
- ws[i] = n & 0x3ffffff;
2318
-
2319
- if (n < 0x4000000) {
2320
- carry = 0;
2321
- } else {
2322
- carry = Math.floor(n / 0x4000000);
2323
- }
2324
- }
2325
-
2326
- return ws;
2327
-}
2328
-
2329
-
2330
-function _inormalize13X(ws, N) {
2331
- var carry = 0;
2332
- for (var i = 0; i < N / 2; ++i) {
2333
-
2334
- //var n = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)
2335
- // + ((ws[2 * i].r / N + .5) >> 0)
2336
- // + carry;
2337
-
2338
- //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {
2339
- // console.log(1 << 13, 1 * 0x2000);
2340
- // 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));
2341
- // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");
2342
- //}
2343
-
2344
- //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)
2345
- //
2346
- //var n = (Math.round(ws[2 * i + 1].r / N) * 0x2000)
2347
- // + Math.round(ws[2 * i].r / N)
2348
- // + carry;
2349
-
2350
- var n = (Math.round(ws[2 * i + 1] / N) * 0x2000)
2351
+ var w = (Math.round(ws[2 * i + 1] / N) * 0x2000)
2352
+ Math.round(ws[2 * i] / N)
2353
+ carry;
2354
2355
- //console.log(
2356
- // n.toString(16),
2357
- // carry.toString(16),
2358
- // (n & 0x3ffffff).toString(16)
2359
- // );
2360
+ ws[i] = w & 0x3ffffff;
2361
2362
- ws[i] = n & 0x3ffffff;
2363
-
2364
- if (n < 0x4000000) {
2365
+ if (w < 0x4000000) {
2366
carry = 0;
2367
} else {
2368
- carry = Math.floor(n / 0x4000000);
2369
+ carry = Math.floor(w / 0x4000000);
2370
}
2371
}
2372
2373
return ws;
2374
}
2375
2376
-function _inormalize20(ws, N) {
2377
-
2378
- var carry = 0;
2379
- var seek = 0;
2380
-
2381
- for (var j = 0; j < N; ++j) {
2382
- ws[j] = Math.round(ws[j].r / N);
2383
- }
2384
-
2385
- for (var i = 0; i < N; ++i) {
2386
- //var w = (((ws[2 * i + 1].r / N + .5) >> 0) << 13)
2387
- // + ((ws[2 * i].r / N + .5) >> 0)
2388
- // + carry;
2389
-
2390
- //if ((Math.round(ws[2 * i + 1].r / N) << 13) !== (Math.round(ws[2 * i + 1].r / N) * 0x2000)) {
2391
- // console.log(1 << 13, 1 * 0x2000);
2392
- // 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));
2393
- // assert((Math.round(ws[2 * i + 1].r / N) << 13) === (Math.round(ws[2 * i + 1].r / N) * 0x2000), "WAAAAAT");
2394
- //}
2395
-
2396
- //assert(Math.abs(ws[2 * i].i) < N && Math.abs(ws[2 * i + 1].i) < N)
2397
-
2398
- //var w = ws[i];
2399
- //
2400
- //assert(w < (0x4000000 * 0x4000000))
2401
- //
2402
- //console.log("Before ", w, w & 0x3ffffff, carry);
2403
- //
2404
- //if (i + 1 < N) {
2405
- // w += ((ws[i + 1] + 0.5) & 0x3ffffff) * 0x100000;
2406
- //
2407
- // ws[i + 1] &= 0x4000000;
2408
- //}
2409
- //
2410
- //w += carry;
2411
- //
2412
- //ws[i] = w & 0x3ffffff;
2413
- //
2414
- //carry = Math.floor(w / 0x4000000);
2415
- //
2416
- //console.log("After ", w, w & 0x3ffffff, carry);
2417
-
2418
- var w = ws[i];
2419
-
2420
- //console.log(w, carry, (w & 0x3ffffff));
2421
-
2422
- var j = i;
2423
-
2424
- //if (w < 0x4000000)
2425
- {
2426
- var pseek = seek;
2427
- seek += 26 - 20;
2428
-
2429
- if (seek > 20) {
2430
- if (i < N - 1) {
2431
- w += ws[i + 1] * 0x100000 / (1 << pseek)
2432
-
2433
- // !!!
2434
- ++i;
2435
-
2436
- seek -= 20;
2437
-
2438
- var d = 1 << seek;
2439
-
2440
- w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);
2441
- ws[i + 1] /= d;
2442
- }
2443
- }
2444
- else
2445
- {
2446
- var pd = 1 << (pseek);
2447
- var d = 1 << (seek);
2448
-
2449
- //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)
2450
-
2451
- w += (ws[i + 1] & (d - 1)) * 0x100000 / pd;
2452
- ws[i + 1] /= d;
2453
- }
2454
- }
2455
-
2456
- //console.log(w, w & 0x3ffffff, carry)
2457
-
2458
- assert(w < 0x4000000 * 0x4000000)
2459
- assert(carry < 0x4000000 * 0x4000000)
2460
-
2461
- w += carry;
2462
-
2463
- //console.log(w, w & 0x3ffffff, carry)
2464
-
2465
- ws[j] = w & 0x3ffffff;
2466
-
2467
- carry = Math.floor(w / 0x4000000);
2468
- }
2469
-
2470
- return ws;
2471
-}
2472
-
2473
-function _inormalize18(ws, N) {
2474
-
2475
- var carry = 0;
2476
- var seek = 0;
2477
-
2478
- for (var j = 0; j < N; ++j) {
2479
- ws[j] = Math.round(ws[j].r / N);
2480
- }
2481
-
2482
- for (var i = 0; i < N; ++i) {
2483
- var w = ws[i];
2484
-
2485
- //console.log(w, carry, (w & 0x3ffffff));
2486
-
2487
- var j = i;
2488
-
2489
- //if (w < 0x4000000)
2490
- {
2491
- var pseek = seek;
2492
- seek += 26 - 18;
2493
-
2494
- if (seek > 18) {
2495
- if (i < N - 1) {
2496
- w += ws[i + 1] * 0x40000 / (1 << pseek)
2497
-
2498
- // !!!
2499
- ++i;
2500
-
2501
- seek -= 18;
2502
-
2503
- var d = 1 << seek;
2504
-
2505
- w += (ws[i + 1] & (d - 1)) * (1 << 26 - seek);
2506
- ws[i + 1] /= d;
2507
- }
2508
- }
2509
- else
2510
- {
2511
- var pd = 1 << (pseek);
2512
- var d = 1 << (seek);
2513
-
2514
- //console.log("D, W, WS[i+1]x ", d, w, (ws[i + 1] & (d - 1)) * 0x100000 / pd)
2515
-
2516
- w += (ws[i + 1] & (d - 1)) * 0x40000 / pd;
2517
- ws[i + 1] /= d;
2518
- }
2519
- }
2520
-
2521
- //console.log(w, w & 0x3ffffff, carry)
2522
-
2523
- assert(w < 0x4000000 * 0x4000000)
2524
- assert(carry < 0x4000000 * 0x4000000)
2525
-
2526
- w += carry;
2527
-
2528
- //console.log(w, w & 0x3ffffff, carry)
2529
-
2530
- ws[j] = w & 0x3ffffff;
2531
-
2532
- carry = Math.floor(w / 0x4000000);
2533
- }
2534
-
2535
- return ws;
2536
-}
2537
-
2538
-
2539
-function _iconvertToC13(ws, N) {
2540
- var cws = new Array(N);
2541
- for (var i = 0; i < N / 2; i++) {
2542
- var w = ws[i] || 0;
2543
-
2544
- cws[2 * i] = new Complex(w & 0x1fff, 0);
2545
- cws[2 * i + 1] = new Complex(w >>> 13, 0);
2546
- }
2547
- return cws;
2548
-}
2549
-
2550
function _iconvertTo13(ws, rws, N) {
2551
for (var i = 0; i < N / 2; i++) {
2552
var w = ws[i] | 0;
2553
@@ -1434,135 +1028,14 @@ function _iconvertTo13(ws, rws, N) {
2554
}
2555
}
2556
2557
-function _iconvertToC20(ws, N) {
2558
- var cws = new Array(N);
2559
-
2560
- for (var i = 0, j = 0, seek = 20; i < N; ++i) {
2561
- var w = ws[i] || 0;
2562
- var l = 26;
2563
-
2564
- while (l > 0) {
2565
- cws[j] = cws[j] || 0;
2566
-
2567
- if (seek >= l) {
2568
- cws[j] += w << (20 - seek);
2569
-
2570
- seek -= l;
2571
- if (seek === 0) seek = 20;
2572
- l = 0;
2573
- } else {
2574
- cws[j] += (w & ((1 << seek) - 1)) << (20 - seek);
2575
- w /= 1 << seek;
2576
-
2577
- ++j;
2578
- l -= seek;
2579
- seek = 20;
2580
- }
2581
- }
2582
- }
2583
-
2584
- for (i = 0; i < N; ++i) {
2585
- cws[i] = new Complex(cws[i], 0);
2586
- }
2587
-
2588
- return cws;
2589
-}
2590
-
2591
-function _iconvertToC18(ws, N) {
2592
- var cws = new Array(N);
2593
-
2594
- for (var i = 0, j = 0, seek = 18; i < N; ++i) {
2595
- var w = ws[i] || 0;
2596
- var l = 26;
2597
-
2598
- while (l > 0) {
2599
- cws[j] = cws[j] || 0;
2600
-
2601
- if (seek >= l) {
2602
- cws[j] += w << (18 - seek);
2603
-
2604
- seek -= l;
2605
- if (seek === 0) seek = 18;
2606
- l = 0;
2607
- } else {
2608
- cws[j] += (w & ((1 << seek) - 1)) << (18 - seek);
2609
- w /= 1 << seek;
2610
-
2611
- ++j;
2612
- l -= seek;
2613
- seek = 18;
2614
- }
2615
- }
2616
- }
2617
-
2618
- for (i = 0; i < N; ++i) {
2619
- cws[i] = new Complex(cws[i], 0);
2620
- }
2621
+function _makePlaceHolderA(N) {
2622
+ var ph = new Array(N);
2623
+ for (var i = 0; i < N; ++i)
2624
+ ph[i] = 0;
2625
2626
- return cws;
2627
+ return ph;
2628
}
2629
2630
-//function _iconvertTo13(ws, N) {
2631
-// var cws = new Array(N);
2632
-// var carry = 0;
2633
-//
2634
-// var i = 0;
2635
-// for (i = 0; i < N; ++i) {
2636
-// ws[i] = Math.round(ws[i].r / N);
2637
-// }
2638
-//
2639
-// i = 0;
2640
-// for (var j = 0; true; ++j) {
2641
-//
2642
-// if (carry < 0x2000) {
2643
-// if (i === N)
2644
-// break;
2645
-//
2646
-// carry += ws[i];
2647
-// i++;
2648
-// }
2649
-//
2650
-// var lo = carry & 0x1fff; // Here we don't care about overflow, since
2651
-// // since overflow may only "screw" (trim) high-order
2652
-// // bits, while we're particularly interested in low-order ones
2653
-//
2654
-// //console.log(carry, lo)
2655
-//
2656
-// carry = carry / 0x2000; // Since shift would trigger conversion from
2657
-// // float (64) to int (32)
2658
-//
2659
-// cws[j] = lo;
2660
-// }
2661
-//
2662
-// //for (var i = 0; i < N; i++) {
2663
-// // carry += Math.round(ws[i].r / N);
2664
-// //
2665
-// //
2666
-// // var lo = carry & 0x1fff; // Here we don't care about overflow, since
2667
-// // // since overflow may only "screw" (trim) high-order
2668
-// // // bits, while we're particularly interested in low-order ones
2669
-// //
2670
-// // console.log(carry, lo)
2671
-// //
2672
-// // carry = carry / 0x2000; // Since shift would trigger conversion from
2673
-// // // float (64) to int (32)
2674
-// //
2675
-// // cws[i] = lo;
2676
-// //}
2677
-//
2678
-// return cws;
2679
-//}
2680
-
2681
-BN.prototype.mulTo = function mulTo(num, out) {
2682
- var res;
2683
- //if (this.length + num.length < 63)
2684
- // res = this._smallMulTo(num, out);
2685
- //else
2686
- res = this._bigMulTo(num, out);
2687
- // res = this._bigMulToF(num, out);
2688
- return res;
2689
-};
2690
-
2691
BN.prototype.mulToF = function mulToF(num, out) {
2692
var res;
2693
//if (this.length + num.length < 63)
2694
@@ -1578,29 +1051,10 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
2695
out.length = this.length + num.length;
2696
2697
var N = 2 * _guess13(this.length, num.length);
2698
- //var N = _guess13(this.length * 1.3, num.length * 1.3);
2699
-
2700
- //var w = new Complex(Math.cos(2 * π / N), Math.sin(2 * π / N));
2701
-
2702
- //console.log("-- W -- ", w);
2703
-
2704
- //var thisWFT = new Array(N),
2705
- // numWFT = new Array(N),
2706
- // //multWFT = new Array(N),
2707
- // multW = new Array(N);
2708
-
2709
- //console.log("A, B: ", this, num);
2710
2711
var rbt = _makeRBT(N);
2712
2713
- //_FFT(_iconvertToC13(this.words, N), 0, 0, thisWFT, 0, w, N);
2714
- //_FFT(_iconvertToC13(num.words, N), 0, 0, numWFT, 0, w, N);
2715
- //_FFT(_iconvertToC20(this.words, N), 0, 0, thisWFT, 0, w, N);
2716
- //_FFT(_iconvertToC20(num.words, N), 0, 0, numWFT, 0, w, N);
2717
- //_FFT(_iconvertToC18(this.words, N), 0, 0, thisWFT, 0, w, N);
2718
- //_FFT(_iconvertToC18(num.words, N), 0, 0, numWFT, 0, w, N);
2719
-
2720
- var ph = _makePlaceHolderA(N),
2721
+ var _ = _makePlaceHolderA(N),
2722
2723
rThisWs = new Array(N),
2724
rThisWsT = new Array(N), // T for Transformed
2725
@@ -1615,62 +1069,29 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
2726
_iconvertTo13(this.words, rThisWs, N);
2727
_iconvertTo13(num.words, rNumWs, N);
2728
2729
- _FFTL(rThisWs, ph, 0, 0, rThisWsT, iThisWsT, 0, 0, N, rbt);
2730
-
2731
- //console.log("X[R/I] Vanilla", _toArray(rThisWs), _toArray(iThisWs))
2732
- //console.log("X[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))
2733
-
2734
- _FFTL(rNumWs, ph, 0, 0, rNumWsT, iNumWsT, 0, 0, N, rbt);
2735
-
2736
- //console.log("Y[R/I] Vanilla", _toArray(rNumWs), _toArray(iNumWs))
2737
- //console.log("Y[R/I] Transformed", _toArray(rNumWsT), _toArray(iNumWsT))
2738
+ _FFTL(rThisWs, _, rThisWsT, iThisWsT, N, rbt);
2739
+ _FFTL(rNumWs, _, rNumWsT, iNumWsT, N, rbt);
2740
2741
for (var i = 0; i < N; ++i) {
2742
- //thisWFT[i].imul(numWFT[i]);
2743
var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];
2744
2745
iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]
2746
rThisWsT[i] = rx;
2747
}
2748
2749
- //console.log("X * Y[R/I] Transformed", _toArray(rThisWsT), _toArray(iThisWsT))
2750
-
2751
- //console.log("-- MULF -- ", multWFT);
2752
-
2753
- //_FFT(_iconjugate(multWFT, N), 0, 0, multW, 0, w, N);
2754
+ _iconjugate(rThisWsT, iThisWsT, N);
2755
2756
- _iconjugateX(rThisWsT, iThisWsT, N);
2757
+ _FFTL(rThisWsT, iThisWsT, rMultWs, _, N, rbt);
2758
2759
- //console.log("X * Y[R/I] Transformed Conjugated", _toArray(rThisWsT), _toArray(iThisWsT))
2760
+ _iconjugate(rMultWs, _, N);
2761
2762
- _FFTL(rThisWsT, iThisWsT, 0, 0, rMultWs, ph, 0, 0, N, rbt);
2763
-
2764
- //console.log("X * Y[R/I] Inverse FFT", _toArray(rMultWs), _toArray(iMultWs))
2765
-
2766
- _iconjugateX(rMultWs, ph, N);
2767
-
2768
- _inormalize13X(rMultWs, N);
2769
-
2770
- //console.log("X * Y[R/I] Conjugated Normalized", _toArray(rMultWs), _toArray(iMultWs))
2771
-
2772
- //multW = _inormalize20(_iconjugate(multW, N), N);
2773
- //multW = _inormalize18(_iconjugate(multW, N), N);
2774
+ _inormalize13(rMultWs, N);
2775
2776
out.words = rMultWs;
2777
2778
- //console.log("-- MUL -- ", multW);
2779
-
2780
return out.strip();
2781
};
2782
2783
-function _makePlaceHolderA(N) {
2784
- var ph = new Array(N);
2785
- for (var i = 0; i < N; ++i)
2786
- ph[i] = 0;
2787
-
2788
- return ph;
2789
-}
2790
-
2791
2792
// Multiply `this` by `num`
2793
BN.prototype.mul = function mul(num) {
2794
diff --git a/test/_fft.js b/test/_fft.js
2795
deleted file mode 100644
2796
index 40237ed..0000000
2797
--- a/test/_fft.js
2798
+++ /dev/null
2799
@@ -1,49 +0,0 @@
2800
-var BN = require("../lib/bn.js").BN
2801
-var fixtures = require("./fixtures.js")
2802
-
2803
-//var a = new BN("1");
2804
-//var b = new BN("1");
2805
-
2806
-//var a = new BN("2");
2807
-//var b = new BN("13");
2808
-
2809
-//var a = new BN("123");
2810
-//var b = new BN("123");
2811
-
2812
-//var a = new BN("12345");
2813
-//var b = new BN("1");
2814
-
2815
-//var a = new BN("123456");
2816
-//var b = new BN("123456");
2817
-
2818
-//var a = new BN("12345690");
2819
-//var b = new BN("1234560");
2820
-
2821
-//var a = new BN("123456900");
2822
-//var b = new BN("12345601");
2823
-
2824
-//var a = new BN("0x2000", 16);
2825
-//var b = new BN("12345678");
2826
-
2827
-//var a = new BN("123456789");
2828
-//var b = new BN("123456789");
2829
-
2830
-//var a = new BN(
2831
-// '13f29a3e0bc10e100ce0', 16);
2832
-//var b = a.clone();
2833
-
2834
-
2835
-var a = new BN(fixtures.dhGroups.p17.q, 16);
2836
-var b = a.clone();
2837
-var qs = fixtures.dhGroups.p17.qs;
2838
-
2839
-var c = a.mulf(b);
2840
-var c_ = a.mul(b);
2841
-
2842
-//console.log(c.words);
2843
-console.log(c);
2844
-console.log("------")
2845
-//console.log(c_.words);
2846
-console.log(c_);
2847
-
2848
-//assert(c === new BN(2))
2849
2850
From 955d90d26efa344490afa0daabf582c1517037da Mon Sep 17 00:00:00 2001
2851
From: Alexey Kudinkin <[email protected]>
2852
Date: Tue, 16 Dec 2014 02:26:35 +0300
2853
Subject: [PATCH 08/12] Tidying up
2854
2855
---
2856
lib/bn.js | 65 +++++++++++++++++++++++++++++----------------------------------
2857
1 file changed, 30 insertions(+), 35 deletions(-)
2858
2859
diff --git a/lib/bn.js b/lib/bn.js
2860
index c1aaedd..745641c 100644
2861
--- a/lib/bn.js
2862
+++ b/lib/bn.js
2863
@@ -898,22 +898,20 @@ BN.prototype.mulTo = function mulTo(num, out) {
2864
2865
// Private
2866
2867
-var π = 3.14159265359;
2868
-
2869
function _FFTL(rws, iws, rtws, itws, N, rbt) {
2870
_permuteTo(rbt, rws, iws, rtws, itws, N);
2871
2872
for (var s = 1; s < N; s <<= 1) {
2873
- var l = s << 1;
2874
+ var l = s << 1;
2875
2876
- var rtwdf = Math.cos(2 * π / l);
2877
- var itwdf = Math.sin(2 * π / l);
2878
+ var rtwdf = Math.cos(2 * Math.PI / l);
2879
+ var itwdf = Math.sin(2 * Math.PI / l);
2880
2881
for (var p = 0; p < N; p += l) {
2882
var rtwdf_ = rtwdf;
2883
var itwdf_ = itwdf;
2884
2885
- for (var j = 0; j < s; ++j) {
2886
+ for (var j = 0; j < s; j++) {
2887
2888
var re = rtws[p + j];
2889
var ie = itws[p + j];
2890
@@ -946,7 +944,7 @@ function _FFTL(rws, iws, rtws, itws, N, rbt) {
2891
function _makeRBT(N) {
2892
var t = new Array(N);
2893
var l = (Math.log(N) / Math.log(2)) >> 0;
2894
- for (var i = 0; i < N; ++i) {
2895
+ for (var i = 0; i < N; i++) {
2896
t[i] = _revbin(i, l, N);
2897
}
2898
2899
@@ -954,7 +952,7 @@ function _makeRBT(N) {
2900
}
2901
2902
function _permuteTo(rbt, rws, iws, rtws, itws, N) {
2903
- for (var i = 0; i < N; ++i) {
2904
+ for (var i = 0; i < N; i++) {
2905
rtws[i] = rws[rbt[i]];
2906
itws[i] = iws[rbt[i]];
2907
}
2908
@@ -965,7 +963,7 @@ function _revbin(x, l, N) {
2909
return x;
2910
2911
var rb = 0;
2912
- for (var i = 0; i < l; ++i) {
2913
+ for (var i = 0; i < l; i++) {
2914
rb |= (x & 1) << (l - i - 1);
2915
x >>= 1;
2916
}
2917
@@ -986,33 +984,33 @@ function _guess13(n, m) {
2918
2919
function _iconjugate(rws, iws, N) {
2920
if (N > 1) {
2921
- for (var i = 0; i < N / 2; ++i) {
2922
+ for (var i = 0; i < N / 2; i++) {
2923
var t = rws[i];
2924
2925
- rws[i] = rws[N - i - 1];
2926
- rws[N - i - 1] = t;
2927
+ rws[i] = rws[N - i - 1];
2928
+ rws[N - i - 1] = t;
2929
2930
t = iws[i];
2931
2932
- iws[i] = -iws[N - i - 1];
2933
- iws[N - i - 1] = -t;
2934
+ iws[i] = -iws[N - i - 1];
2935
+ iws[N - i - 1] = -t;
2936
}
2937
}
2938
}
2939
2940
function _inormalize13(ws, N) {
2941
var carry = 0;
2942
- for (var i = 0; i < N / 2; ++i) {
2943
- var w = (Math.round(ws[2 * i + 1] / N) * 0x2000)
2944
- + Math.round(ws[2 * i] / N)
2945
- + carry;
2946
+ for (var i = 0; i < N / 2; i++) {
2947
+ var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
2948
+ Math.round(ws[2 * i] / N) +
2949
+ carry;
2950
2951
ws[i] = w & 0x3ffffff;
2952
2953
if (w < 0x4000000) {
2954
carry = 0;
2955
} else {
2956
- carry = Math.floor(w / 0x4000000);
2957
+ carry = w / 0x4000000 | 0;
2958
}
2959
}
2960
2961
@@ -1023,14 +1021,14 @@ function _iconvertTo13(ws, rws, N) {
2962
for (var i = 0; i < N / 2; i++) {
2963
var w = ws[i] | 0;
2964
2965
- rws[2 * i] = w & 0x1fff;
2966
- rws[2 * i + 1] = w >>> 13;
2967
+ rws[2 * i] = w & 0x1fff;
2968
+ rws[2 * i + 1] = w >>> 13;
2969
}
2970
}
2971
2972
function _makePlaceHolderA(N) {
2973
var ph = new Array(N);
2974
- for (var i = 0; i < N; ++i)
2975
+ for (var i = 0; i < N; i++)
2976
ph[i] = 0;
2977
2978
return ph;
2979
@@ -1038,10 +1036,7 @@ function _makePlaceHolderA(N) {
2980
2981
BN.prototype.mulToF = function mulToF(num, out) {
2982
var res;
2983
- //if (this.length + num.length < 63)
2984
- // res = this._smallMulTo(num, out);
2985
- //else
2986
- res = this._bigMulToF(num, out);
2987
+ res = this._bigMulToF(num, out);
2988
return res;
2989
};
2990
2991
@@ -1054,17 +1049,17 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
2992
2993
var rbt = _makeRBT(N);
2994
2995
- var _ = _makePlaceHolderA(N),
2996
+ var _ = _makePlaceHolderA(N),
2997
2998
- rThisWs = new Array(N),
2999
- rThisWsT = new Array(N), // T for Transformed
3000
- iThisWsT = new Array(N),
3001
+ rThisWs = new Array(N),
3002
+ rThisWsT = new Array(N), // T for Transformed
3003
+ iThisWsT = new Array(N),
3004
3005
- rNumWs = new Array(N),
3006
- rNumWsT = new Array(N),
3007
- iNumWsT = new Array(N),
3008
+ rNumWs = new Array(N),
3009
+ rNumWsT = new Array(N),
3010
+ iNumWsT = new Array(N),
3011
3012
- rMultWs = new Array(N);
3013
+ rMultWs = new Array(N);
3014
3015
_iconvertTo13(this.words, rThisWs, N);
3016
_iconvertTo13(num.words, rNumWs, N);
3017
@@ -1072,7 +1067,7 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
3018
_FFTL(rThisWs, _, rThisWsT, iThisWsT, N, rbt);
3019
_FFTL(rNumWs, _, rNumWsT, iNumWsT, N, rbt);
3020
3021
- for (var i = 0; i < N; ++i) {
3022
+ for (var i = 0; i < N; i++) {
3023
var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];
3024
3025
iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]
3026
3027
From 22f4a713b509e7166d05ee800de5dff863a3bd7c Mon Sep 17 00:00:00 2001
3028
From: Alexey Kudinkin <[email protected]>
3029
Date: Fri, 19 Dec 2014 20:48:02 +0300
3030
Subject: [PATCH 09/12] Extracted FFT multiplier as class; Minor cosmetic fixes
3031
3032
---
3033
lib/bn.js | 158 ++++++++++++++++++++++++++++++++------------------------------
3034
1 file changed, 81 insertions(+), 77 deletions(-)
3035
3036
diff --git a/lib/bn.js b/lib/bn.js
3037
index 745641c..285a08d 100644
3038
--- a/lib/bn.js
3039
+++ b/lib/bn.js
3040
@@ -898,8 +898,43 @@ BN.prototype.mulTo = function mulTo(num, out) {
3041
3042
// Private
3043
3044
-function _FFTL(rws, iws, rtws, itws, N, rbt) {
3045
- _permuteTo(rbt, rws, iws, rtws, itws, N);
3046
+var FFTM = function (x, y) {
3047
+ this.x = x;
3048
+ this.y = y;
3049
+}
3050
+
3051
+FFTM.prototype.make_rbt = function (N) {
3052
+ var t = new Array(N);
3053
+ var l = (Math.log(N) / Math.log(2)) >> 0;
3054
+ for (var i = 0; i < N; i++) {
3055
+ t[i] = this.revbin(i, l, N);
3056
+ }
3057
+
3058
+ return t;
3059
+}
3060
+
3061
+FFTM.prototype.revbin = function (x, l, N) {
3062
+ if (x === 0 || x === N - 1)
3063
+ return x;
3064
+
3065
+ var rb = 0;
3066
+ for (var i = 0; i < l; i++) {
3067
+ rb |= (x & 1) << (l - i - 1);
3068
+ x >>= 1;
3069
+ }
3070
+
3071
+ return rb;
3072
+}
3073
+
3074
+FFTM.prototype.permute = function (rbt, rws, iws, rtws, itws, N) {
3075
+ for (var i = 0; i < N; i++) {
3076
+ rtws[i] = rws[rbt[i]];
3077
+ itws[i] = iws[rbt[i]];
3078
+ }
3079
+}
3080
+
3081
+FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {
3082
+ this.permute(rbt, rws, iws, rtws, itws, N);
3083
3084
for (var s = 1; s < N; s <<= 1) {
3085
var l = s << 1;
3086
@@ -931,7 +966,7 @@ function _FFTL(rws, iws, rtws, itws, N, rbt) {
3087
itws[p + j + s] = ie - io;
3088
3089
if (j !== l) {
3090
- var rx = rtwdf * rtwdf_ - itwdf * itwdf_;
3091
+ rx = rtwdf * rtwdf_ - itwdf * itwdf_;
3092
3093
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
3094
rtwdf_ = rx;
3095
@@ -941,48 +976,18 @@ function _FFTL(rws, iws, rtws, itws, N, rbt) {
3096
}
3097
}
3098
3099
-function _makeRBT(N) {
3100
- var t = new Array(N);
3101
- var l = (Math.log(N) / Math.log(2)) >> 0;
3102
- for (var i = 0; i < N; i++) {
3103
- t[i] = _revbin(i, l, N);
3104
- }
3105
-
3106
- return t;
3107
-}
3108
-
3109
-function _permuteTo(rbt, rws, iws, rtws, itws, N) {
3110
- for (var i = 0; i < N; i++) {
3111
- rtws[i] = rws[rbt[i]];
3112
- itws[i] = iws[rbt[i]];
3113
- }
3114
-}
3115
-
3116
-function _revbin(x, l, N) {
3117
- if (x === 0 || x === N - 1)
3118
- return x;
3119
-
3120
- var rb = 0;
3121
- for (var i = 0; i < l; i++) {
3122
- rb |= (x & 1) << (l - i - 1);
3123
- x >>= 1;
3124
- }
3125
-
3126
- return rb;
3127
-}
3128
-
3129
-
3130
-function _guess13(n, m) {
3131
- var N = Math.max(m, n) | 1, odd = N & 1;
3132
+FFTM.prototype.guess_len_13b = function (n, m) {
3133
+ var N = Math.max(m, n) | 1;
3134
+ var odd = N & 1;
3135
var i = 0;
3136
while (N = N / 2 >> 0) {
3137
i++;
3138
}
3139
3140
- return (1 << i + 1 + odd)
3141
+ return 1 << i + 1 + odd;
3142
}
3143
3144
-function _iconjugate(rws, iws, N) {
3145
+FFTM.prototype.conjugate = function (rws, iws, N) {
3146
if (N > 1) {
3147
for (var i = 0; i < N / 2; i++) {
3148
var t = rws[i];
3149
@@ -998,7 +1003,7 @@ function _iconjugate(rws, iws, N) {
3150
}
3151
}
3152
3153
-function _inormalize13(ws, N) {
3154
+FFTM.prototype.normalize_13b = function (ws, N) {
3155
var carry = 0;
3156
for (var i = 0; i < N / 2; i++) {
3157
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
3158
@@ -1017,7 +1022,7 @@ function _inormalize13(ws, N) {
3159
return ws;
3160
}
3161
3162
-function _iconvertTo13(ws, rws, N) {
3163
+FFTM.prototype.convert_13b = function (ws, rws, N) {
3164
for (var i = 0; i < N / 2; i++) {
3165
var w = ws[i] | 0;
3166
3167
@@ -1026,46 +1031,39 @@ function _iconvertTo13(ws, rws, N) {
3168
}
3169
}
3170
3171
-function _makePlaceHolderA(N) {
3172
- var ph = new Array(N);
3173
- for (var i = 0; i < N; i++)
3174
- ph[i] = 0;
3175
+FFTM.prototype.mulp = function () {
3176
+ function stub(N) {
3177
+ var ph = new Array(N);
3178
+ for (var i = 0; i < N; i++)
3179
+ ph[i] = 0;
3180
3181
- return ph;
3182
-}
3183
+ return ph;
3184
+ }
3185
3186
-BN.prototype.mulToF = function mulToF(num, out) {
3187
- var res;
3188
- res = this._bigMulToF(num, out);
3189
- return res;
3190
-};
3191
+ var x = this.x;
3192
+ var y = this.y;
3193
3194
+ var N = 2 * this.guess_len_13b(x.length, y.length);
3195
3196
-BN.prototype._bigMulToF = function _bigMulToF(num, out) {
3197
- out.sign = num.sign !== this.sign;
3198
- out.length = this.length + num.length;
3199
+ var rbt = this.make_rbt(N);
3200
3201
- var N = 2 * _guess13(this.length, num.length);
3202
+ var _ = stub(N),
3203
3204
- var rbt = _makeRBT(N);
3205
+ rThisWs = new Array(N),
3206
+ rThisWsT = new Array(N), // T for Transformed
3207
+ iThisWsT = new Array(N),
3208
3209
- var _ = _makePlaceHolderA(N),
3210
+ rNumWs = new Array(N),
3211
+ rNumWsT = new Array(N),
3212
+ iNumWsT = new Array(N),
3213
3214
- rThisWs = new Array(N),
3215
- rThisWsT = new Array(N), // T for Transformed
3216
- iThisWsT = new Array(N),
3217
+ rMultWs = new Array(N);
3218
3219
- rNumWs = new Array(N),
3220
- rNumWsT = new Array(N),
3221
- iNumWsT = new Array(N),
3222
+ this.convert_13b(x.words, rThisWs, N);
3223
+ this.convert_13b(y.words, rNumWs, N);
3224
3225
- rMultWs = new Array(N);
3226
-
3227
- _iconvertTo13(this.words, rThisWs, N);
3228
- _iconvertTo13(num.words, rNumWs, N);
3229
-
3230
- _FFTL(rThisWs, _, rThisWsT, iThisWsT, N, rbt);
3231
- _FFTL(rNumWs, _, rNumWsT, iNumWsT, N, rbt);
3232
+ this.transform(rThisWs, _, rThisWsT, iThisWsT, N, rbt);
3233
+ this.transform(rNumWs, _, rNumWsT, iNumWsT, N, rbt);
3234
3235
for (var i = 0; i < N; i++) {
3236
var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];
3237
@@ -1074,15 +1072,22 @@ BN.prototype._bigMulToF = function _bigMulToF(num, out) {
3238
rThisWsT[i] = rx;
3239
}
3240
3241
- _iconjugate(rThisWsT, iThisWsT, N);
3242
+ this.conjugate(rThisWsT, iThisWsT, N);
3243
+
3244
+ this.transform(rThisWsT, iThisWsT, rMultWs, _, N, rbt);
3245
+
3246
+ this.conjugate(rMultWs, _, N);
3247
3248
- _FFTL(rThisWsT, iThisWsT, rMultWs, _, N, rbt);
3249
+ this.normalize_13b(rMultWs, N);
3250
3251
- _iconjugate(rMultWs, _, N);
3252
+ return rMultWs;
3253
+}
3254
3255
- _inormalize13(rMultWs, N);
3256
+BN.prototype._bigMulToF = function _bigMulToF(num, out) {
3257
+ out.sign = num.sign !== this.sign;
3258
+ out.length = this.length + num.length;
3259
3260
- out.words = rMultWs;
3261
+ out.words = (new FFTM(this, num)).mulp();
3262
3263
return out.strip();
3264
};
3265
@@ -1098,9 +1103,8 @@ BN.prototype.mul = function mul(num) {
3266
// Multiply employing FFT
3267
BN.prototype.mulf = function mulf(num) {
3268
var out = new BN(null);
3269
- //out.words = new Array(this.length + num.length);
3270
out.words = null;
3271
- return this.mulToF(num, out);
3272
+ return this._bigMulToF(num, out);
3273
};
3274
3275
// In-place Multiplication
3276
3277
From c51b380a9acb25b1c09cb805ec708e836e921a00 Mon Sep 17 00:00:00 2001
3278
From: Alexey Kudinkin <[email protected]>
3279
Date: Sun, 11 Jan 2015 06:12:05 +0300
3280
Subject: [PATCH 10/12] Minor style fixes
3281
3282
---
3283
lib/bn.js | 36 ++++++++++++++++++------------------
3284
1 file changed, 18 insertions(+), 18 deletions(-)
3285
3286
diff --git a/lib/bn.js b/lib/bn.js
3287
index 285a08d..7705741 100644
3288
--- a/lib/bn.js
3289
+++ b/lib/bn.js
3290
@@ -898,12 +898,12 @@ BN.prototype.mulTo = function mulTo(num, out) {
3291
3292
// Private
3293
3294
-var FFTM = function (x, y) {
3295
+function FFTM(x, y) {
3296
this.x = x;
3297
this.y = y;
3298
}
3299
3300
-FFTM.prototype.make_rbt = function (N) {
3301
+FFTM.prototype.makeRBT = function makeRBT(N) {
3302
var t = new Array(N);
3303
var l = (Math.log(N) / Math.log(2)) >> 0;
3304
for (var i = 0; i < N; i++) {
3305
@@ -913,7 +913,7 @@ FFTM.prototype.make_rbt = function (N) {
3306
return t;
3307
}
3308
3309
-FFTM.prototype.revbin = function (x, l, N) {
3310
+FFTM.prototype.revbin = function revbin(x, l, N) {
3311
if (x === 0 || x === N - 1)
3312
return x;
3313
3314
@@ -926,14 +926,14 @@ FFTM.prototype.revbin = function (x, l, N) {
3315
return rb;
3316
}
3317
3318
-FFTM.prototype.permute = function (rbt, rws, iws, rtws, itws, N) {
3319
+FFTM.prototype.permute = function permute(rbt, rws, iws, rtws, itws, N) {
3320
for (var i = 0; i < N; i++) {
3321
rtws[i] = rws[rbt[i]];
3322
itws[i] = iws[rbt[i]];
3323
}
3324
}
3325
3326
-FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {
3327
+FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {
3328
this.permute(rbt, rws, iws, rtws, itws, N);
3329
3330
for (var s = 1; s < N; s <<= 1) {
3331
@@ -947,7 +947,6 @@ FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {
3332
var itwdf_ = itwdf;
3333
3334
for (var j = 0; j < s; j++) {
3335
-
3336
var re = rtws[p + j];
3337
var ie = itws[p + j];
3338
3339
@@ -976,7 +975,7 @@ FFTM.prototype.transform = function (rws, iws, rtws, itws, N, rbt) {
3340
}
3341
}
3342
3343
-FFTM.prototype.guess_len_13b = function (n, m) {
3344
+FFTM.prototype.guessLen13b = function guessLen13b(n, m) {
3345
var N = Math.max(m, n) | 1;
3346
var odd = N & 1;
3347
var i = 0;
3348
@@ -988,18 +987,19 @@ FFTM.prototype.guess_len_13b = function (n, m) {
3349
}
3350
3351
FFTM.prototype.conjugate = function (rws, iws, N) {
3352
- if (N > 1) {
3353
- for (var i = 0; i < N / 2; i++) {
3354
- var t = rws[i];
3355
+ if (N <= 1)
3356
+ return;
3357
3358
- rws[i] = rws[N - i - 1];
3359
- rws[N - i - 1] = t;
3360
+ for (var i = 0; i < N / 2; i++) {
3361
+ var t = rws[i];
3362
3363
- t = iws[i];
3364
+ rws[i] = rws[N - i - 1];
3365
+ rws[N - i - 1] = t;
3366
3367
- iws[i] = -iws[N - i - 1];
3368
- iws[N - i - 1] = -t;
3369
- }
3370
+ t = iws[i];
3371
+
3372
+ iws[i] = -iws[N - i - 1];
3373
+ iws[N - i - 1] = -t;
3374
}
3375
}
3376
3377
@@ -1043,9 +1043,9 @@ FFTM.prototype.mulp = function () {
3378
var x = this.x;
3379
var y = this.y;
3380
3381
- var N = 2 * this.guess_len_13b(x.length, y.length);
3382
+ var N = 2 * this.guessLen13b(x.length, y.length);
3383
3384
- var rbt = this.make_rbt(N);
3385
+ var rbt = this.makeRBT(N);
3386
3387
var _ = stub(N),
3388
3389
3390
From 72f5498499baec7b4052550892ca52caff33d21c Mon Sep 17 00:00:00 2001
3391
From: Alexey Kudinkin <[email protected]>
3392
Date: Mon, 12 Jan 2015 17:21:43 +0300
3393
Subject: [PATCH 11/12] Continuous style fixes
3394
3395
---
3396
lib/bn.js | 16 +++++++---------
3397
1 file changed, 7 insertions(+), 9 deletions(-)
3398
3399
diff --git a/lib/bn.js b/lib/bn.js
3400
index 7705741..7081948 100644
3401
--- a/lib/bn.js
3402
+++ b/lib/bn.js
3403
@@ -905,7 +905,7 @@ function FFTM(x, y) {
3404
3405
FFTM.prototype.makeRBT = function makeRBT(N) {
3406
var t = new Array(N);
3407
- var l = (Math.log(N) / Math.log(2)) >> 0;
3408
+ var l = (Math.log(N) / Math.log(2)) | 0;
3409
for (var i = 0; i < N; i++) {
3410
t[i] = this.revbin(i, l, N);
3411
}
3412
@@ -979,7 +979,7 @@ FFTM.prototype.guessLen13b = function guessLen13b(n, m) {
3413
var N = Math.max(m, n) | 1;
3414
var odd = N & 1;
3415
var i = 0;
3416
- while (N = N / 2 >> 0) {
3417
+ while (N = N / 2 | 0) {
3418
i++;
3419
}
3420
3421
@@ -1003,7 +1003,7 @@ FFTM.prototype.conjugate = function (rws, iws, N) {
3422
}
3423
}
3424
3425
-FFTM.prototype.normalize_13b = function (ws, N) {
3426
+FFTM.prototype.normalize13b = function (ws, N) {
3427
var carry = 0;
3428
for (var i = 0; i < N / 2; i++) {
3429
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
3430
@@ -1022,7 +1022,7 @@ FFTM.prototype.normalize_13b = function (ws, N) {
3431
return ws;
3432
}
3433
3434
-FFTM.prototype.convert_13b = function (ws, rws, N) {
3435
+FFTM.prototype.convert13b = function (ws, rws, N) {
3436
for (var i = 0; i < N / 2; i++) {
3437
var w = ws[i] | 0;
3438
3439
@@ -1059,8 +1059,8 @@ FFTM.prototype.mulp = function () {
3440
3441
rMultWs = new Array(N);
3442
3443
- this.convert_13b(x.words, rThisWs, N);
3444
- this.convert_13b(y.words, rNumWs, N);
3445
+ this.convert13b(x.words, rThisWs, N);
3446
+ this.convert13b(y.words, rNumWs, N);
3447
3448
this.transform(rThisWs, _, rThisWsT, iThisWsT, N, rbt);
3449
this.transform(rNumWs, _, rNumWsT, iNumWsT, N, rbt);
3450
@@ -1078,7 +1078,7 @@ FFTM.prototype.mulp = function () {
3451
3452
this.conjugate(rMultWs, _, N);
3453
3454
- this.normalize_13b(rMultWs, N);
3455
+ this.normalize13b(rMultWs, N);
3456
3457
return rMultWs;
3458
}
3459
@@ -1086,7 +1086,6 @@ FFTM.prototype.mulp = function () {
3460
BN.prototype._bigMulToF = function _bigMulToF(num, out) {
3461
out.sign = num.sign !== this.sign;
3462
out.length = this.length + num.length;
3463
-
3464
out.words = (new FFTM(this, num)).mulp();
3465
3466
return out.strip();
3467
@@ -1103,7 +1102,6 @@ BN.prototype.mul = function mul(num) {
3468
// Multiply employing FFT
3469
BN.prototype.mulf = function mulf(num) {
3470
var out = new BN(null);
3471
- out.words = null;
3472
return this._bigMulToF(num, out);
3473
};
3474
3475
3476
From b3b5d959b6cb9dd2f8fc270fe8a64b9a54151d1c Mon Sep 17 00:00:00 2001
3477
From: Alexey Kudinkin <[email protected]>
3478
Date: Mon, 9 Feb 2015 23:43:13 +0300
3479
Subject: [PATCH 12/12] Sligthly refurbished overall style; Fixed lint issues
3480
3481
---
3482
lib/bn.js | 63 +++++++++++++++++++++++++++++++--------------------------------
3483
1 file changed, 31 insertions(+), 32 deletions(-)
3484
3485
diff --git a/lib/bn.js b/lib/bn.js
3486
index 7081948..5b553e4 100644
3487
--- a/lib/bn.js
3488
+++ b/lib/bn.js
3489
@@ -911,7 +911,7 @@ FFTM.prototype.makeRBT = function makeRBT(N) {
3490
}
3491
3492
return t;
3493
-}
3494
+};
3495
3496
FFTM.prototype.revbin = function revbin(x, l, N) {
3497
if (x === 0 || x === N - 1)
3498
@@ -924,14 +924,14 @@ FFTM.prototype.revbin = function revbin(x, l, N) {
3499
}
3500
3501
return rb;
3502
-}
3503
+};
3504
3505
FFTM.prototype.permute = function permute(rbt, rws, iws, rtws, itws, N) {
3506
for (var i = 0; i < N; i++) {
3507
rtws[i] = rws[rbt[i]];
3508
itws[i] = iws[rbt[i]];
3509
}
3510
-}
3511
+};
3512
3513
FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {
3514
this.permute(rbt, rws, iws, rtws, itws, N);
3515
@@ -964,6 +964,7 @@ FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {
3516
rtws[p + j + s] = re - ro;
3517
itws[p + j + s] = ie - io;
3518
3519
+ /* jshint maxdepth : false */
3520
if (j !== l) {
3521
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
3522
3523
@@ -973,18 +974,18 @@ FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) {
3524
}
3525
}
3526
}
3527
-}
3528
+};
3529
3530
FFTM.prototype.guessLen13b = function guessLen13b(n, m) {
3531
var N = Math.max(m, n) | 1;
3532
var odd = N & 1;
3533
var i = 0;
3534
- while (N = N / 2 | 0) {
3535
+ for (N = N / 2 | 0; N; N = N / 2 | 0) {
3536
i++;
3537
}
3538
3539
return 1 << i + 1 + odd;
3540
-}
3541
+};
3542
3543
FFTM.prototype.conjugate = function (rws, iws, N) {
3544
if (N <= 1)
3545
@@ -1001,7 +1002,7 @@ FFTM.prototype.conjugate = function (rws, iws, N) {
3546
iws[i] = -iws[N - i - 1];
3547
iws[N - i - 1] = -t;
3548
}
3549
-}
3550
+};
3551
3552
FFTM.prototype.normalize13b = function (ws, N) {
3553
var carry = 0;
3554
@@ -1020,7 +1021,7 @@ FFTM.prototype.normalize13b = function (ws, N) {
3555
}
3556
3557
return ws;
3558
-}
3559
+};
3560
3561
FFTM.prototype.convert13b = function (ws, rws, N) {
3562
for (var i = 0; i < N / 2; i++) {
3563
@@ -1029,7 +1030,7 @@ FFTM.prototype.convert13b = function (ws, rws, N) {
3564
rws[2 * i] = w & 0x1fff;
3565
rws[2 * i + 1] = w >>> 13;
3566
}
3567
-}
3568
+};
3569
3570
FFTM.prototype.mulp = function () {
3571
function stub(N) {
3572
@@ -1047,47 +1048,45 @@ FFTM.prototype.mulp = function () {
3573
3574
var rbt = this.makeRBT(N);
3575
3576
- var _ = stub(N),
3577
+ var _ = stub(N);
3578
3579
- rThisWs = new Array(N),
3580
- rThisWsT = new Array(N), // T for Transformed
3581
- iThisWsT = new Array(N),
3582
+ var rws = new Array(N);
3583
+ var rwst = new Array(N);
3584
+ var iwst = new Array(N);
3585
3586
- rNumWs = new Array(N),
3587
- rNumWsT = new Array(N),
3588
- iNumWsT = new Array(N),
3589
+ var nrws = new Array(N);
3590
+ var nrwst = new Array(N);
3591
+ var niwst = new Array(N);
3592
3593
- rMultWs = new Array(N);
3594
+ var rmws = new Array(N);
3595
3596
- this.convert13b(x.words, rThisWs, N);
3597
- this.convert13b(y.words, rNumWs, N);
3598
+ this.convert13b(x.words, rws, N);
3599
+ this.convert13b(y.words, nrws, N);
3600
3601
- this.transform(rThisWs, _, rThisWsT, iThisWsT, N, rbt);
3602
- this.transform(rNumWs, _, rNumWsT, iNumWsT, N, rbt);
3603
+ this.transform(rws, _, rwst, iwst, N, rbt);
3604
+ this.transform(nrws, _, nrwst, niwst, N, rbt);
3605
3606
for (var i = 0; i < N; i++) {
3607
- var rx = rThisWsT[i] * rNumWsT[i] - iThisWsT[i] * iNumWsT[i];
3608
-
3609
- iThisWsT[i] = rThisWsT[i] * iNumWsT[i] + iThisWsT[i] * rNumWsT[i]
3610
- rThisWsT[i] = rx;
3611
+ var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
3612
+ iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
3613
+ rwst[i] = rx;
3614
}
3615
3616
- this.conjugate(rThisWsT, iThisWsT, N);
3617
+ this.conjugate(rwst, iwst, N);
3618
3619
- this.transform(rThisWsT, iThisWsT, rMultWs, _, N, rbt);
3620
+ this.transform(rwst, iwst, rmws, _, N, rbt);
3621
3622
- this.conjugate(rMultWs, _, N);
3623
+ this.conjugate(rmws, _, N);
3624
3625
- this.normalize13b(rMultWs, N);
3626
+ this.normalize13b(rmws, N);
3627
3628
- return rMultWs;
3629
-}
3630
+ return rmws;
3631
+};
3632
3633
BN.prototype._bigMulToF = function _bigMulToF(num, out) {
3634
out.sign = num.sign !== this.sign;
3635
out.length = this.length + num.length;
3636
out.words = (new FFTM(this, num)).mulp();
3637
-
3638
return out.strip();
3639
};
3640
3641
3642