pyret-npm 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4311 @@
1
+ // Modifications to Danny Yoo's js-numbers library, whose LICENSE is:
2
+
3
+ /*
4
+
5
+ Licensing
6
+ ---------
7
+
8
+ This software is covered under the following copyright:
9
+
10
+ *
11
+ * Copyright (c) 2010 Danny Yoo
12
+ * All Rights Reserved.
13
+ *
14
+ * Permission is hereby granted, free of charge, to any person obtaining
15
+ * a copy of this software and associated documentation files (the
16
+ * "Software"), to deal in the Software without restriction, including
17
+ * without limitation the rights to use, copy, modify, merge, publish,
18
+ * distribute, sublicense, and/or sell copies of the Software, and to
19
+ * permit persons to whom the Software is furnished to do so, subject to
20
+ * the following conditions:
21
+ *
22
+ * The above copyright notice and this permission notice shall be
23
+ * included in all copies or substantial portions of the Software.
24
+ *
25
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
26
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
27
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
28
+ *
29
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
30
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
31
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
32
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
33
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34
+ *
35
+ * In addition, the following condition applies:
36
+ *
37
+ * All redistributions must retain an intact copy of this copyright notice
38
+ * and disclaimer.
39
+ *
40
+
41
+ ======================================================================
42
+
43
+ js-numbers uses code from the jsbn library. The LICENSE to it is:
44
+
45
+ Licensing
46
+ ---------
47
+
48
+ This software is covered under the following copyright:
49
+
50
+ *
51
+ * Copyright (c) 2003-2005 Tom Wu
52
+ * All Rights Reserved.
53
+ *
54
+ * Permission is hereby granted, free of charge, to any person obtaining
55
+ * a copy of this software and associated documentation files (the
56
+ * "Software"), to deal in the Software without restriction, including
57
+ * without limitation the rights to use, copy, modify, merge, publish,
58
+ * distribute, sublicense, and/or sell copies of the Software, and to
59
+ * permit persons to whom the Software is furnished to do so, subject to
60
+ * the following conditions:
61
+ *
62
+ * The above copyright notice and this permission notice shall be
63
+ * included in all copies or substantial portions of the Software.
64
+ *
65
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
66
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
67
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
68
+ *
69
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
70
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
71
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
72
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
73
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
74
+ *
75
+ * In addition, the following condition applies:
76
+ *
77
+ * All redistributions must retain an intact copy of this copyright notice
78
+ * and disclaimer.
79
+ *
80
+
81
+ Address all questions regarding this license to:
82
+
83
+ Tom Wu
84
+ tjw@cs.Stanford.EDU
85
+
86
+ */
87
+
88
+ /*
89
+
90
+ No notion of levels (complex, exact, inexact, flonum).
91
+
92
+ No complex numbers.
93
+
94
+ Added roughnums.
95
+
96
+ pyretnum := fixnum | boxnum
97
+
98
+ A fixnum is simply a JS double, and we prefer to use them
99
+ whenever possible, viz., for integers that are small enough.
100
+
101
+ boxnum := BigInteger | Rational | Roughnum.
102
+
103
+ An integer is either a fixnum or a BigInteger.
104
+
105
+ */
106
+
107
+ define("pyret-base/js/js-numbers", function() {
108
+ 'use strict';
109
+ function MakeNumberLibrary(errbacks) {
110
+ // Abbreviation
111
+ var Numbers = {};
112
+
113
+ // makeNumericBinop: (fixnum fixnum -> any) (pyretnum pyretnum -> any) -> (pyretnum pyretnum) X
114
+ // Creates a binary function that works either on fixnums or boxnums.
115
+ // Applies the appropriate binary function, ensuring that both pyretnums are
116
+ // coerced to be the same kind.
117
+ var makeNumericBinop = function(onFixnums, onBoxednums, options) {
118
+ options = options || {};
119
+ return function(x, y) {
120
+
121
+ if (options.isXSpecialCase && options.isXSpecialCase(x))
122
+ return options.onXSpecialCase(x, y);
123
+ if (options.isYSpecialCase && options.isYSpecialCase(y))
124
+ return options.onYSpecialCase(x, y);
125
+
126
+ if (typeof(x) === 'number' &&
127
+ typeof(y) === 'number') {
128
+ return onFixnums(x, y);
129
+ }
130
+
131
+ if (typeof(x) === 'number') {
132
+ x = liftFixnumInteger(x, y);
133
+ }
134
+ if (typeof(y) === 'number') {
135
+ y = liftFixnumInteger(y, x);
136
+ }
137
+
138
+ if (x instanceof Roughnum) {
139
+ // y is rough, rat or bigint
140
+ if (!(y instanceof Roughnum)) {
141
+ // y is rat or bigint
142
+ y = y.toRoughnum();
143
+ }
144
+ } else if (y instanceof Roughnum) {
145
+ // x is rat or bigint
146
+ x = x.toRoughnum();
147
+ } else if (x instanceof Rational) {
148
+ // y is rat or bigint
149
+ if (!(y instanceof Rational)) {
150
+ // y is bigint
151
+ y = new Rational(y, 1);
152
+ }
153
+ } else if (y instanceof Rational) {
154
+ // x is bigint
155
+ x = new Rational(x, 1);
156
+ }
157
+
158
+ return onBoxednums(x, y);
159
+ };
160
+ };
161
+
162
+ // fromFixnum: fixnum -> pyretnum
163
+ var fromFixnum = function(x) {
164
+ return fromString(String(x));
165
+ };
166
+
167
+ var expandExponent = function(s) {
168
+ var match = s.match(scientificPattern), mantissaChunks, exponent;
169
+ if (match) {
170
+ mantissaChunks = match[1].match(/^([^.]*)(.*)$/);
171
+ exponent = Number(match[2]);
172
+
173
+ if (mantissaChunks[2].length === 0) {
174
+ return mantissaChunks[1] + zfill(exponent);
175
+ }
176
+
177
+ if (exponent >= mantissaChunks[2].length - 1) {
178
+ return (mantissaChunks[1] +
179
+ mantissaChunks[2].substring(1) +
180
+ zfill(exponent - (mantissaChunks[2].length - 1)));
181
+ } else {
182
+ return (mantissaChunks[1] +
183
+ mantissaChunks[2].substring(1, 1+exponent));
184
+ }
185
+ } else {
186
+ return s;
187
+ }
188
+ };
189
+
190
+ // zfill: integer -> string
191
+ // builds a string of "0"'s of length n.
192
+ var zfill = function(n) {
193
+ var buffer = [];
194
+ buffer.length = n;
195
+ for (var i = 0; i < n; i++) {
196
+ buffer[i] = '0';
197
+ }
198
+ return buffer.join('');
199
+ };
200
+
201
+ // liftFixnumInteger: fixnum-integer boxed-pyretnum -> boxed-pyretnum
202
+ // Lifts up fixnum integers to a boxed type.
203
+
204
+ var liftFixnumInteger = function(x, other) {
205
+ if (other instanceof Roughnum)
206
+ return new Roughnum(x);
207
+ else if (other instanceof BigInteger)
208
+ return makeBignum(x);
209
+ else
210
+ return fromFixnum(x);
211
+ };
212
+
213
+
214
+ // isPyretNumber: any -> boolean
215
+ // Pure predicate. Raw JS numbers must be integers (the fixnum
216
+ // representation) to count as pyretnums; non-integer JS numbers
217
+ // are not valid pyretnums and return false.
218
+ var isPyretNumber = function(thing) {
219
+ if (typeof(thing) === 'number') return Number.isInteger(thing);
220
+ return (thing instanceof Rational ||
221
+ thing instanceof Roughnum ||
222
+ thing instanceof BigInteger);
223
+ };
224
+
225
+ // assertPyretNumber: contract check for entry-point operations that
226
+ // require a pyretnum. Throws a domainError for clearly wrong types
227
+ // (string, null, etc.). For non-integer JS numbers, logs to
228
+ // console.error rather than throwing — we don't yet have full
229
+ // coverage of all call sites that may pass these in, and an
230
+ // exception in the wild from existing code we haven't audited would
231
+ // be worse than the current lax behavior. Flip the non-integer
232
+ // branch to errbacks.throwDomainError once we're confident.
233
+ var assertPyretNumber = function(thing, callerName) {
234
+ if (typeof thing === 'number') {
235
+ if (!Number.isInteger(thing)) {
236
+ console.error(
237
+ 'js-numbers ' + callerName +
238
+ ': non-integer JS number leaked into pyretnum: ' + thing,
239
+ new Error('stack').stack);
240
+ }
241
+ return;
242
+ }
243
+ if (thing instanceof Rational ||
244
+ thing instanceof Roughnum ||
245
+ thing instanceof BigInteger) {
246
+ return;
247
+ }
248
+ errbacks.throwDomainError(
249
+ callerName + ': arg ' + thing + ' is not a number.');
250
+ };
251
+
252
+ // isRational: pyretnum -> boolean
253
+ var isRational = function(n) {
254
+ if (!isPyretNumber(n)) return false;
255
+ if (typeof(n) === 'number') return true;
256
+ return n.isRational();
257
+ };
258
+
259
+ var isExact = isRational;
260
+
261
+ // isReal: pyretnum -> boolean
262
+ var isReal = function(n) {
263
+ if (!isPyretNumber(n)) return false;
264
+ if (typeof(n) === 'number') return true;
265
+ return n.isReal();
266
+ };
267
+
268
+ // isInteger: pyretnum -> boolean
269
+ var isInteger = function(n) {
270
+ if (!isPyretNumber(n)) return false;
271
+ if (typeof(n) === 'number') return true;
272
+ return n.isInteger();
273
+ };
274
+
275
+ var isRoughnum = function(n) {
276
+ if (!isPyretNumber(n)) return false;
277
+ if (typeof(n) === 'number') return false;
278
+ return n.isRoughnum();
279
+ };
280
+
281
+ var isPositive = function(n) {
282
+ if (!isPyretNumber(n)) return false;
283
+ if (typeof(n) === 'number') return n > 0;
284
+ return n.isPositive();
285
+ };
286
+
287
+ var isNonPositive = function(n) {
288
+ if (!isPyretNumber(n)) return false;
289
+ if (typeof(n) === 'number') return n <= 0;
290
+ return n.isNonPositive();
291
+ };
292
+
293
+ var isNegative = function(n) {
294
+ if (!isPyretNumber(n)) return false;
295
+ if (typeof(n) === 'number') return n < 0;
296
+ return n.isNegative();
297
+ };
298
+
299
+ var isNonNegative = function(n) {
300
+ if (!isPyretNumber(n)) return false;
301
+ if (typeof(n) === 'number') return n >= 0;
302
+ return n.isNonNegative();
303
+ };
304
+
305
+ // toFixnum: pyretnum -> javascript-number
306
+ var toFixnum = function(n) {
307
+ assertPyretNumber(n, 'toFixnum');
308
+ if (typeof(n) === 'number') return n;
309
+ return n.toFixnum();
310
+ };
311
+
312
+ // toRational: pyretnum -> pyretnum
313
+ var toRational = function(n) {
314
+ if (typeof(n) === 'number')
315
+ return n;
316
+ return n.toRational();
317
+ };
318
+
319
+ var toExact = toRational;
320
+
321
+ // toRoughnum: pyretnum -> pyretnum
322
+
323
+ var toRoughnum = function(n) {
324
+ if (typeof(n) === 'number') {
325
+ return Roughnum.makeInstance(n);
326
+ } else {
327
+ return n.toRoughnum();
328
+ }
329
+ };
330
+
331
+ //////////////////////////////////////////////////////////////////////
332
+
333
+ // add: pyretnum pyretnum -> pyretnum
334
+ var add = function(x, y) {
335
+ var sum;
336
+ if (typeof(x) === 'number' && typeof(y) === 'number') {
337
+ sum = x + y;
338
+ if (isOverflow(sum)) {
339
+ return (makeBignum(x)).add(makeBignum(y));
340
+ }
341
+ else {
342
+ return sum;
343
+ }
344
+ }
345
+ return addSlow(x, y);
346
+ };
347
+
348
+ var addSlow = makeNumericBinop(
349
+ function(x, y) {
350
+ var sum = x + y;
351
+ if (isOverflow(sum)) {
352
+ return (makeBignum(x)).add(makeBignum(y));
353
+ } else {
354
+ return sum;
355
+ }
356
+ },
357
+ function(x, y) {
358
+ return x.add(y);
359
+ },
360
+ {isXSpecialCase: function(x) {
361
+ return isInteger(x) && _integerIsZero(x) },
362
+ onXSpecialCase: function(x, y) { return y; },
363
+ isYSpecialCase: function(y) {
364
+ return isInteger(y) && _integerIsZero(y) },
365
+ onYSpecialCase: function(x, y) { return x; }
366
+ });
367
+
368
+ var subtract = function(x, y) {
369
+ if (typeof(x) === 'number' && typeof(y) === 'number') {
370
+ var diff = x - y;
371
+ if (isOverflow(diff)) {
372
+ return (makeBignum(x)).subtract(makeBignum(y));
373
+ } else {
374
+ return diff;
375
+ }
376
+ }
377
+ return subtractSlow(x, y);
378
+ };
379
+
380
+ // subtract: pyretnum pyretnum -> pyretnum
381
+ var subtractSlow = makeNumericBinop(
382
+ function(x, y) {
383
+ var diff = x - y;
384
+ if (isOverflow(diff)) {
385
+ return (makeBignum(x)).subtract(makeBignum(y));
386
+ } else {
387
+ return diff;
388
+ }
389
+ },
390
+ function(x, y) {
391
+ return x.subtract(y);
392
+ },
393
+ {isXSpecialCase: function(x) {
394
+ return isInteger(x) && _integerIsZero(x) },
395
+ onXSpecialCase: function(x, y) { return negate(y); },
396
+ isYSpecialCase: function(y) {
397
+ return isInteger(y) && _integerIsZero(y) },
398
+ onYSpecialCase: function(x, y) { return x; }
399
+ });
400
+
401
+ // mulitply: pyretnum pyretnum -> pyretnum
402
+ var multiply = function(x, y) {
403
+ var prod;
404
+ if (typeof(x) === 'number' && typeof(y) === 'number') {
405
+ prod = x * y;
406
+ if (isOverflow(prod)) {
407
+ return (makeBignum(x)).multiply(makeBignum(y));
408
+ } else {
409
+ return prod;
410
+ }
411
+ }
412
+ return multiplySlow(x, y);
413
+ };
414
+ var multiplySlow = makeNumericBinop(
415
+ function(x, y) {
416
+ var prod = x * y;
417
+ if (isOverflow(prod)) {
418
+ return (makeBignum(x)).multiply(makeBignum(y));
419
+ } else {
420
+ return prod;
421
+ }
422
+ },
423
+ function(x, y) {
424
+ return x.multiply(y);
425
+ },
426
+ {isXSpecialCase: function(x) {
427
+ return (isInteger(x) &&
428
+ (_integerIsZero(x) || _integerIsOne(x) || _integerIsNegativeOne(x))) },
429
+ onXSpecialCase: function(x, y) {
430
+ if (_integerIsZero(x))
431
+ return 0;
432
+ if (_integerIsOne(x))
433
+ return y;
434
+ if (_integerIsNegativeOne(x))
435
+ return negate(y);
436
+ },
437
+ isYSpecialCase: function(y) {
438
+ return (isInteger(y) &&
439
+ (_integerIsZero(y) || _integerIsOne(y) || _integerIsNegativeOne(y)))},
440
+ onYSpecialCase: function(x, y) {
441
+ if (_integerIsZero(y))
442
+ return 0;
443
+ if (_integerIsOne(y))
444
+ return x;
445
+ if (_integerIsNegativeOne(y))
446
+ return negate(x);
447
+ }
448
+ });
449
+
450
+ // divide: pyretnum pyretnum -> pyretnum
451
+ var divide = makeNumericBinop(
452
+ function(x, y) {
453
+ if (_integerIsZero(y))
454
+ errbacks.throwDivByZero("/: division by zero, " + x + ' ' + y);
455
+ var div = x / y;
456
+ if (isOverflow(div)) {
457
+ return (makeBignum(x)).divide(makeBignum(y));
458
+ } else if (Math.floor(div) !== div) {
459
+ return Rational.makeInstance(x, y);
460
+ } else {
461
+ return div;
462
+ }
463
+ },
464
+ function(x, y) {
465
+ if (equalsAnyZero(y)) {
466
+ errbacks.throwDivByZero('/: division by zero, ' + x + ' ' + y);
467
+ }
468
+ return x.divide(y);
469
+ },
470
+ {
471
+ isXSpecialCase: function(x) {
472
+ return equalsAnyZero(x);
473
+ },
474
+ onXSpecialCase: function(x, y) {
475
+ if (equalsAnyZero(y)) {
476
+ errbacks.throwDivByZero("/: division by zero, " + x + ' ' + y);
477
+ }
478
+ return 0;
479
+ },
480
+ isYSpecialCase: function(y) {
481
+ return equalsAnyZero(y);
482
+ },
483
+ onYSpecialCase: function(x, y) {
484
+ errbacks.throwDivByZero("/: division by zero, " + x + ' ' + y);
485
+ }
486
+ });
487
+
488
+ var equals = function(x, y) {
489
+ if (x === y) { return true; }
490
+ else {
491
+ if (typeof x === "number" && typeof y === "number") { return false; }
492
+ else {
493
+ return equalsSlow(x, y);
494
+ }
495
+ }
496
+ };
497
+ // equals: pyretnum pyretnum -> boolean
498
+ var equalsSlow = makeNumericBinop(
499
+ function(x, y) {
500
+ return x === y;
501
+ },
502
+ function(x, y) {
503
+ return x.equals(y);
504
+ });
505
+
506
+ var equalsAnyZero = function(x) {
507
+ if (typeof(x) === 'number') return x === 0;
508
+ if (isRoughnum(x)) return x.n === 0;
509
+ return x.equals(0);
510
+ };
511
+
512
+ // eqv: pyretnum pyretnum -> boolean
513
+ var eqv = function(x, y) {
514
+ if (x === y)
515
+ return true;
516
+ if (typeof(x) === 'number' && typeof(y) === 'number')
517
+ return x === y;
518
+ var ex = isRational(x), ey = isRational(y);
519
+ return (((ex && ey) || (!ex && !ey)) && equals(x, y));
520
+ };
521
+
522
+ // approxEqual: pyretnum pyretnum pyretnum -> boolean
523
+ var approxEquals = function(x, y, delta) {
524
+ return lessThanOrEqual(abs(subtract(x, y)),
525
+ delta);
526
+ };
527
+
528
+ // used for within
529
+ var roughlyEquals = function(x, y, delta) {
530
+ if (isNegative(delta)) {
531
+ errbacks.throwToleranceError("negative tolerance " + delta);
532
+ }
533
+
534
+ if (x === y) return true;
535
+
536
+ if (isRoughnum(delta) && delta.n === Number.MIN_VALUE) {
537
+ if ((isRoughnum(x) || isRoughnum(y)) &&
538
+ (Math.abs(subtract(x,y).n) === Number.MIN_VALUE)) {
539
+ errbacks.throwToleranceError("roughnum tolerance too small for meaningful comparison, " + x + ' ' + y + ' ' + delta);
540
+ }
541
+ }
542
+
543
+ var ratx = isRoughnum(x) ? x.toRational() : x;
544
+ var raty = isRoughnum(y) ? y.toRational() : y;
545
+
546
+ var ratdelta = isRoughnum(delta) ? delta.toRational() : delta;
547
+ return approxEquals(ratx, raty, ratdelta);
548
+ };
549
+
550
+ var roughlyEqualsRel = function(computedValue, trueValue, delta, smoothed) {
551
+ if (isNegative(delta)) {
552
+ errbacks.throwRelToleranceError('negative relative tolerance ' + delta)
553
+ }
554
+
555
+ if (computedValue === trueValue) {
556
+ return true
557
+ }
558
+
559
+ var deltaIsRough = isRoughnum(delta)
560
+ var argNumsAreRough = isRoughnum(computedValue) || isRoughnum(trueValue)
561
+
562
+ var ratCv = isRoughnum(computedValue) ? computedValue.toRational() : computedValue
563
+ var ratTv = isRoughnum(trueValue) ? trueValue.toRational() : trueValue
564
+
565
+ var ratDelta = isRoughnum(delta) ? delta.toRational(): delta
566
+
567
+ var err = abs(subtract(ratCv, ratTv))
568
+ var denom = min(abs(ratCv), abs(ratTv))
569
+ if (smoothed) {
570
+ denom = add(denom, 1);
571
+ }
572
+
573
+ if (lessThanOrEqual(ratDelta, 1)) {
574
+ var absDelta = multiply(ratDelta, denom)
575
+ if (deltaIsRough && toRoughnum(absDelta).n === Number.MIN_VALUE) {
576
+ if (argNumsAreRough && Math.abs(toRoughnum(err).n) === Number.MIN_VALUE) {
577
+ errbacks.throwRelToleranceError('roughnum tolerance too small for meaningful comparison, ' +
578
+ computedValue + ' ' + trueValue + ' ' + delta)
579
+ }
580
+ }
581
+
582
+ return lessThanOrEqual(err, absDelta)
583
+ } else {
584
+ var errRatio = divide(err, denom)
585
+
586
+ if (deltaIsRough && delta.n === Number.MIN_VALUE) {
587
+ if (argNumsAreRough && Math.abs(toRoughnum(errRatio).n) === Number.MIN_VALUE) {
588
+ errbacks.throwRelToleranceError('roughnum tolerance too small for meaningful comparison, ' +
589
+ computedValue + ' ' + trueValue + ' ' + delta)
590
+ }
591
+ }
592
+
593
+ return lessThanOrEqual(errRatio, ratDelta)
594
+ }
595
+ }
596
+
597
+ // greaterThanOrEqual: pyretnum pyretnum -> boolean
598
+ var greaterThanOrEqual = function(x, y) {
599
+ if(typeof x === "number" && typeof y === "number") {
600
+ return x >= y;
601
+ }
602
+ return makeNumericBinop(undefined, function(x, y) {
603
+ return x.greaterThanOrEqual(y);
604
+ })(x, y);
605
+ }
606
+
607
+ // lessThanOrEqual: pyretnum pyretnum -> boolean
608
+ var lessThanOrEqual = function(x, y) {
609
+ if(typeof x === "number" && typeof y === "number") {
610
+ return x <= y;
611
+ }
612
+ return makeNumericBinop(undefined, function(x, y) {
613
+ return x.lessThanOrEqual(y);
614
+ })(x, y);
615
+ };
616
+
617
+ // greaterThan: pyretnum pyretnum -> boolean
618
+ var greaterThan = function(x, y) {
619
+ if(typeof x === "number" && typeof y === "number") {
620
+ return x > y;
621
+ }
622
+ return makeNumericBinop(undefined, function(x, y) {
623
+ return x.greaterThan(y);
624
+ })(x, y);
625
+ };
626
+
627
+ // lessThan: pyretnum pyretnum -> boolean
628
+ var lessThan = function(x, y) {
629
+ if(typeof x === "number" && typeof y === "number") {
630
+ return x < y;
631
+ }
632
+ return makeNumericBinop(undefined, function(x, y) {
633
+ return x.lessThan(y);
634
+ })(x, y);
635
+ };
636
+
637
+ // expt: pyretnum pyretnum -> pyretnum
638
+ var expt = makeNumericBinop(
639
+ function(x, y) {
640
+ var pow = Math.pow(x, y);
641
+ if (isOverflow(pow)) {
642
+ return (makeBignum(x)).expt(makeBignum(y));
643
+ } else {
644
+ return pow;
645
+ }
646
+ },
647
+ function(x, y) {
648
+ return x.expt(y);
649
+ },
650
+ {
651
+ isXSpecialCase: function(x) {
652
+ return eqv(x, 0) || eqv(x, 1);
653
+ },
654
+ onXSpecialCase: function(x, y) {
655
+ if (eqv(x, 0)) {
656
+ if (eqv(y, 0)) {
657
+ return 1;
658
+ } else if (lessThan(y, 0)) {
659
+ errbacks.throwDivByZero("expt: division by zero");
660
+ } else {
661
+ return 0;
662
+ }
663
+ } else { // i.e., x is 1
664
+ return 1;
665
+ }
666
+ },
667
+
668
+ isYSpecialCase: function(y) {
669
+ return eqv(y, 0) || lessThan(y, 0);
670
+ },
671
+ onYSpecialCase: function(x, y) {
672
+ if (eqv(y, 0)) {
673
+ return 1;
674
+ } else { // i.e., y is negative
675
+ return expt(divide(1, x), negate(y));
676
+ }
677
+ }
678
+ });
679
+
680
+ // exp: pyretnum -> pyretnum
681
+ var exp = function(n) {
682
+ if ( eqv(n, 0) ) {
683
+ return 1;
684
+ }
685
+ if (typeof(n) === 'number') {
686
+ var res = Math.exp(n);
687
+ if (!isFinite(res))
688
+ errbacks.throwGeneralError('exp: argument too large: ' + n);
689
+ return Roughnum.makeInstance(res);
690
+ }
691
+ return n.exp();
692
+ };
693
+
694
+ // modulo: pyretnum pyretnum -> pyretnum
695
+ var modulo = function(m, n) {
696
+ if (! isInteger(m)) {
697
+ errbacks.throwDomainError('modulo: the first argument '
698
+ + m + " is not an integer.", m, n);
699
+ }
700
+ if (! isInteger(n)) {
701
+ errbacks.throwDomainError('modulo: the second argument '
702
+ + n + " is not an integer.", m, n);
703
+ }
704
+ if (_integerIsZero(n)) {
705
+ errbacks.throwDomainError('modulo: the second argument is zero');
706
+ }
707
+ var result;
708
+ if (typeof(m) === 'number') {
709
+ result = m % n;
710
+ if (n < 0) {
711
+ if (result <= 0)
712
+ return result;
713
+ else
714
+ return result + n;
715
+ } else {
716
+ if (result < 0)
717
+ return result + n;
718
+ else
719
+ return result;
720
+ }
721
+ }
722
+ result = _integerModulo(floor(m), floor(n));
723
+ // The sign of the result should match the sign of n.
724
+ if (lessThan(n, 0)) {
725
+ if (lessThanOrEqual(result, 0)) {
726
+ return result;
727
+ }
728
+ return add(result, n);
729
+
730
+ } else {
731
+ if (lessThan(result, 0)) {
732
+ return add(result, n);
733
+ }
734
+ return result;
735
+ }
736
+ };
737
+
738
+ // numerator: pyretnum -> pyretnum
739
+ var numerator = function(n) {
740
+ if (typeof(n) === 'number')
741
+ return n;
742
+ return n.numerator();
743
+ };
744
+
745
+ // denominator: pyretnum -> pyretnum
746
+ var denominator = function(n) {
747
+ if (typeof(n) === 'number')
748
+ return 1;
749
+ return n.denominator();
750
+ };
751
+
752
+ // sqrt: pyretnum -> pyretnum
753
+ var sqrt = function(n) {
754
+ if (lessThan(n, 0)) {
755
+ errbacks.throwSqrtNegative('sqrt: negative argument ' + n);
756
+ }
757
+ if (typeof(n) === 'number') {
758
+ var result = Math.sqrt(n);
759
+ if (Math.floor(result) === result) {
760
+ return result;
761
+ } else {
762
+ return Roughnum.makeInstance(result);
763
+ }
764
+ }
765
+ return n.sqrt();
766
+ };
767
+
768
+ // abs: pyretnum -> pyretnum
769
+ var abs = function(n) {
770
+ if (typeof(n) === 'number') {
771
+ return Math.abs(n);
772
+ }
773
+ return n.abs();
774
+ };
775
+
776
+ // min :: pyretnum, pyretnum -> pyretnum
777
+ var min = function(n, m) {
778
+ if (lessThan(n, m)) {
779
+ return n;
780
+ }
781
+ return m;
782
+ }
783
+
784
+
785
+ // floor: pyretnum -> pyretnum
786
+ var floor = function(n) {
787
+ if (typeof(n) === 'number')
788
+ return Math.floor(n);
789
+ return n.floor();
790
+ };
791
+
792
+ // ceiling: pyretnum -> pyretnum
793
+ var ceiling = function(n) {
794
+ if (typeof(n) === 'number')
795
+ return Math.ceil(n);
796
+ return n.ceiling();
797
+ };
798
+
799
+ // round: pyretnum -> pyretnum
800
+ var round = function(n) {
801
+ if (typeof(n) === 'number') {
802
+ return n;
803
+ }
804
+ return n.round();
805
+ };
806
+
807
+ var roundEven = function(n) {
808
+ if (typeof(n) === 'number') return n;
809
+ return n.roundEven();
810
+ };
811
+
812
+ // NB: all of these trig-gy generic functions should now return roughnum rather than float
813
+ // (except for an arg of 0, etc)
814
+
815
+ var ln10 = Math.log(10)
816
+
817
+ // log: pyretnum -> pyretnum
818
+ var log = function(n) {
819
+ if ( eqv(n, 1) ) {
820
+ return 0;
821
+ }
822
+ if (lessThanOrEqual(n, 0)) {
823
+ errbacks.throwLogNonPositive('log: non-positive argument ' + n);
824
+ }
825
+ if (typeof(n) === 'number') {
826
+ return Roughnum.makeInstance(Math.log(n));
827
+ }
828
+ if (isRational(n) && !isInteger(n)) {
829
+ return subtract(log(numerator(n)),
830
+ log(denominator(n)));
831
+ }
832
+ var nFix = n.toFixnum();
833
+ if (typeof(nFix) === 'number' && nFix !== Infinity) {
834
+ return Roughnum.makeInstance(Math.log(nFix));
835
+ }
836
+ // at this point, n must be a very large positive number;
837
+ // n > 1e308, i.e, has at least 308 digits;
838
+ // we can safely ignore its fractional part;
839
+ var nStr = n.round().toString();
840
+ var nLen = nStr.length;
841
+ // we furthermore need only the integer part's first few digits
842
+ // although we must remember the number of digits ignored;
843
+ var firstFewLen = 308; // has to be <= 308
844
+ // say integer N = yyy...yyyxxx...xxx
845
+ // where the number of x's is nx;
846
+ // So N ~= yyy...yyy * 10^nx
847
+ // We'll first find the common (base 10) log of N
848
+ // log10(N) ~= log10(yyy...yyy * 10^nx)
849
+ // = log10(yyy...yyy) + nx
850
+ // Now to convert this to the natural log
851
+ // ln(N) = log10(N) / log10(e)
852
+ // = log10(N) * ln(10)
853
+ // ~= [log10(yyy...yyy) + nx] * ln(10)
854
+ // = log10(yyy...yyy) * ln(10) + nx * ln(10)
855
+ // = ln(yyy...yyy) + nx * ln(10)
856
+ // JS gives us ln(yyy...yyy) and ln(10) so we have a good
857
+ // approximation for ln(N)
858
+ var nFirstFew = parseInt(nStr.substring(0, firstFewLen));
859
+ var nLog = Math.log(nFirstFew) + (nLen - firstFewLen) * ln10;
860
+ return Roughnum.makeInstance(nLog);
861
+ };
862
+
863
+ // tan: pyretnum -> pyretnum
864
+ var tan = function(n) {
865
+ if (eqv(n, 0)) { return 0; }
866
+ if (typeof(n) === 'number') {
867
+ return Roughnum.makeInstance(Math.tan(n));
868
+ }
869
+ return n.tan();
870
+ };
871
+
872
+ // atan: pyretnum -> pyretnum
873
+ var atan = function(n) {
874
+ if (eqv(n, 0)) { return 0; }
875
+ if (typeof(n) === 'number') {
876
+ return Roughnum.makeInstance(Math.atan(n));
877
+ }
878
+ return n.atan();
879
+ };
880
+
881
+ var atan2 = function(y, x) {
882
+ if (eqv(x, 0)) { // x = 0
883
+ if (eqv(y, 0)) { // x = 0, y = 0
884
+ //return Roughnum.makeInstance(Infinity);
885
+ errbacks.throwDomainError('atan2: out of domain argument (0, 0)');
886
+ } else if (greaterThan(y, 0)) { // x = 0, y > 0
887
+ return Roughnum.makeInstance(Math.PI/2);
888
+ } else { // x = 0, y < 0
889
+ return Roughnum.makeInstance(3*Math.PI/2);
890
+ }
891
+ } else if (greaterThan(x, 0)) { // x > 0
892
+ if (greaterThanOrEqual(y, 0)) { // x > 0, y >= 0, 1st qdt
893
+ // atan(y/x) is already in the right qdt
894
+ return atan(divide(y, x));
895
+ } else { // x > 0, y < 0, 4th qdt
896
+ // atan(y/x) is the 4th qdt and negative, so make it positive by adding 2pi
897
+ return add(atan(divide(y, x)), Roughnum.makeInstance(2*Math.PI));
898
+ }
899
+ } else { // x < 0
900
+ // either x < 0, y >= 0 (2nd qdt), in which case
901
+ // atan(y/x) must be reflected from 4th to 2nd qdt, by adding pi
902
+ // or x < 0, y < 0 (3rd qdt), in which case
903
+ // atan(y/x) must be reflected from 1st to 3rd qdt, again by adding pi
904
+ return add(atan(divide(y, x)), Roughnum.makeInstance(Math.PI));
905
+ }
906
+ };
907
+
908
+ // cos: pyretnum -> pyretnum
909
+ var cos = function(n) {
910
+ if (eqv(n, 0)) { return 1; }
911
+ if (typeof(n) === 'number') {
912
+ return Roughnum.makeInstance(Math.cos(n));
913
+ }
914
+ return n.cos();
915
+ };
916
+
917
+ // sin: pyretnum -> pyretnum
918
+ var sin = function(n) {
919
+ if (eqv(n, 0)) { return 0; }
920
+ if (typeof(n) === 'number') {
921
+ return Roughnum.makeInstance(Math.sin(n));
922
+ }
923
+ return n.sin();
924
+ };
925
+
926
+ // acos: pyretnum -> pyretnum
927
+ var acos = function(n) {
928
+ if (eqv(n, 1)) { return 0; }
929
+ if (lessThan(n, -1) || greaterThan(n, 1)) {
930
+ errbacks.throwDomainError('acos: out of domain argument ' + n);
931
+ }
932
+ if (typeof(n) === 'number') {
933
+ return Roughnum.makeInstance(Math.acos(n));
934
+ }
935
+ return n.acos();
936
+ };
937
+
938
+ // asin: pyretnum -> pyretnum
939
+ var asin = function(n) {
940
+ if (eqv(n, 0)) { return 0; }
941
+ if (lessThan(n, -1) || greaterThan(n, 1)) {
942
+ errbacks.throwDomainError('asin: out of domain argument ' + n);
943
+ }
944
+ if (typeof(n) === 'number') {
945
+ return Roughnum.makeInstance(Math.asin(n));
946
+ }
947
+ return n.asin();
948
+ };
949
+
950
+ // sqr: pyretnum -> pyretnum
951
+ var sqr = function(x) {
952
+ return multiply(x, x);
953
+ };
954
+
955
+ // integerSqrt: pyretnum -> pyretnum
956
+ var integerSqrt = function(x) {
957
+ if (! isInteger(x)) {
958
+ errbacks.throwDomainError('integer-sqrt: the argument ' + x.toString() +
959
+ " is not an integer.", x);
960
+ }
961
+ if (typeof (x) === 'number') {
962
+ if(x < 0) {
963
+ errbacks.throwSqrtNegative('integerSqrt of negative number', x);
964
+ } else {
965
+ return Math.floor(Math.sqrt(x));
966
+ }
967
+ }
968
+ return x.integerSqrt();
969
+ };
970
+
971
+ // gcd: pyretnum pyretnum -> pyretnum
972
+ var gcd = function(first, second) {
973
+ if (! isInteger(first)) {
974
+ errbacks.throwDomainError('gcd: the argument ' + first.toString() +
975
+ " is not an integer.", first);
976
+ }
977
+ if (! isInteger(second)) {
978
+ errbacks.throwDomainError('gcd: the argument ' + second.toString() +
979
+ " is not an integer.", second);
980
+ }
981
+ var a = abs(first), t;
982
+ var b = abs(second);
983
+ while (! _integerIsZero(b)) {
984
+ t = a;
985
+ a = b;
986
+ b = _integerModulo(t, b);
987
+ }
988
+ return a;
989
+ };
990
+
991
+ // lcm: pyretnum pyretnum -> pyretnum
992
+ var lcm = function(first, second) {
993
+ if (! isInteger(first)) {
994
+ errbacks.throwDomainError('lcm: the argument ' + first.toString() +
995
+ " is not an integer.", first);
996
+ }
997
+ if (! isInteger(second)) {
998
+ errbacks.throwDomainError('lcm: the argument ' + second.toString() +
999
+ " is not an integer.", second);
1000
+ }
1001
+ var result = abs(first);
1002
+ if (_integerIsZero(result)) { return 0; }
1003
+ var divisor = _integerGcd(result, second);
1004
+ if (_integerIsZero(divisor)) {
1005
+ return 0;
1006
+ }
1007
+ result = divide(multiply(result, second), divisor);
1008
+ return result;
1009
+ };
1010
+
1011
+ var quotient = function(x, y) {
1012
+ if (! isInteger(x)) {
1013
+ errbacks.throwDomainError('quotient: the first argument ' + x.toString() +
1014
+ " is not an integer.", x);
1015
+ }
1016
+ if (! isInteger(y)) {
1017
+ errbacks.throwDomainError('quotient: the second argument ' + y.toString() +
1018
+ " is not an integer.", y);
1019
+ }
1020
+ return _integerQuotient(x, y);
1021
+ };
1022
+
1023
+ var remainder = function(x, y) {
1024
+ if (isInteger(x) && isInteger(y)) {
1025
+ return _integerRemainder(x, y);
1026
+ } else if (isRational(x) && isRational(y)) {
1027
+ var xn = numerator(x); var xd = denominator(x);
1028
+ var yn = numerator(y); var yd = denominator(y);
1029
+ var new_d = lcm(xd, yd);
1030
+ var new_xn = multiply(xn, divide(new_d, xd));
1031
+ var new_yn = multiply(yn, divide(new_d, yd));
1032
+ return divide(remainder(new_xn, new_yn), new_d);
1033
+ } else {
1034
+ var res = toFixnum(x) % toFixnum(y);
1035
+ return Roughnum.makeInstance(res);
1036
+ }
1037
+ };
1038
+
1039
+ //////////////////////////////////////////////////////////////////////
1040
+
1041
+ // Helpers
1042
+
1043
+ // isOverflow: javascript-number -> boolean
1044
+ // Returns true if we consider the number an overflow.
1045
+ var MIN_FIXNUM = -(9e15);
1046
+ var MAX_FIXNUM = (9e15);
1047
+ var isOverflow = function(n) {
1048
+ return (n < MIN_FIXNUM || MAX_FIXNUM < n);
1049
+ };
1050
+
1051
+ // negate: pyretnum -> pyretnum
1052
+ // multiplies a number times -1.
1053
+ var negate = function(n) {
1054
+ if (typeof(n) === 'number') {
1055
+ return -n;
1056
+ }
1057
+ return n.negate();
1058
+ };
1059
+
1060
+ // halve: pyretnum -> pyretnum
1061
+ // Divide a number by 2.
1062
+ var halve = function(n) {
1063
+ return divide(n, 2);
1064
+ };
1065
+
1066
+ // fastExpt: computes n^k by squaring.
1067
+ // n^k = (n^2)^(k/2)
1068
+ // Assumes k is non-negative integer.
1069
+ var fastExpt = function(n, k) {
1070
+ var acc = 1;
1071
+ while (true) {
1072
+ if (_integerIsZero(k)) {
1073
+ return acc;
1074
+ }
1075
+ if (equals(modulo(k, 2), 0)) {
1076
+ n = multiply(n, n);
1077
+ k = divide(k, 2);
1078
+ } else {
1079
+ acc = multiply(acc, n);
1080
+ k = subtract(k, 1);
1081
+ }
1082
+ }
1083
+ };
1084
+
1085
+ //////////////////////////////////////////////////////////////////////
1086
+ //////////////////////////////////////////////////////////////////////
1087
+ //////////////////////////////////////////////////////////////////////
1088
+ //////////////////////////////////////////////////////////////////////
1089
+ //////////////////////////////////////////////////////////////////////
1090
+
1091
+ // Integer operations
1092
+ // Integers are either represented as fixnums or as BigIntegers.
1093
+
1094
+ // makeIntegerBinop: (fixnum fixnum -> X) (BigInteger BigInteger -> X) -> X
1095
+ // Helper to collect the common logic for coercing integer fixnums or bignums to a
1096
+ // common type before doing an operation.
1097
+ var makeIntegerBinop = function(onFixnums, onBignums, options) {
1098
+ options = options || {};
1099
+ return (function(m, n) {
1100
+ if (m instanceof Rational) {
1101
+ m = numerator(m);
1102
+ }
1103
+
1104
+ if (n instanceof Rational) {
1105
+ n = numerator(n);
1106
+ }
1107
+
1108
+ if (typeof(m) === 'number' && typeof(n) === 'number') {
1109
+ var result = onFixnums(m, n);
1110
+ if (! isOverflow(result) ||
1111
+ (options.ignoreOverflow)) {
1112
+ return result;
1113
+ }
1114
+ }
1115
+ if (m instanceof Roughnum || n instanceof Roughnum) {
1116
+ return Roughnum.makeInstance(
1117
+ onFixnums(toFixnum(m), toFixnum(n)));
1118
+ }
1119
+ if (typeof(m) === 'number') {
1120
+ m = makeBignum(m);
1121
+ }
1122
+ if (typeof(n) === 'number') {
1123
+ n = makeBignum(n);
1124
+ }
1125
+ return onBignums(m, n);
1126
+ });
1127
+ };
1128
+
1129
+ var makeIntegerUnOp = function(onFixnums, onBignums, options) {
1130
+ options = options || {};
1131
+ return (function(m) {
1132
+ if (m instanceof Rational) {
1133
+ m = numerator(m);
1134
+ }
1135
+
1136
+ if (typeof(m) === 'number') {
1137
+ var result = onFixnums(m);
1138
+ if (! isOverflow(result) ||
1139
+ (options.ignoreOverflow)) {
1140
+ return result;
1141
+ }
1142
+ }
1143
+ if (m instanceof Roughnum) {
1144
+ return Roughnum.makeInstance(onFixnums(toFixnum(m)));
1145
+ }
1146
+ if (typeof(m) === 'number') {
1147
+ m = makeBignum(m);
1148
+ }
1149
+ return onBignums(m);
1150
+ });
1151
+ };
1152
+
1153
+ // _integerModulo: integer-pyretnum integer-pyretnum -> integer-pyretnum
1154
+ var _integerModulo = makeIntegerBinop(
1155
+ function(m, n) {
1156
+ return m % n;
1157
+ },
1158
+ function(m, n) {
1159
+ return bnMod.call(m, n);
1160
+ });
1161
+
1162
+ // _integerGcd: integer-pyretnum integer-pyretnum -> integer-pyretnum
1163
+ var _integerGcd = makeIntegerBinop(
1164
+ function(a, b) {
1165
+ var t;
1166
+ while (b !== 0) {
1167
+ t = a;
1168
+ a = b;
1169
+ b = t % b;
1170
+ }
1171
+ return a;
1172
+ },
1173
+ function(m, n) {
1174
+ return bnGCD.call(m, n);
1175
+ });
1176
+
1177
+ // _integerIsZero: integer-pyretnum -> boolean
1178
+ // Returns true if the number is zero.
1179
+ var _integerIsZero = makeIntegerUnOp(
1180
+ function(n){
1181
+ return n === 0;
1182
+ },
1183
+ function(n) {
1184
+ return bnEquals.call(n, BigInteger.ZERO);
1185
+ }
1186
+ );
1187
+
1188
+ // _integerIsOne: integer-pyretnum -> boolean
1189
+ var _integerIsOne = makeIntegerUnOp(
1190
+ function(n) {
1191
+ return n === 1;
1192
+ },
1193
+ function(n) {
1194
+ return bnEquals.call(n, BigInteger.ONE);
1195
+ });
1196
+
1197
+ // _integerIsNegativeOne: integer-pyretnum -> boolean
1198
+ var _integerIsNegativeOne = makeIntegerUnOp(
1199
+ function(n) {
1200
+ return n === -1;
1201
+ },
1202
+ function(n) {
1203
+ return bnEquals.call(n, BigInteger.NEGATIVE_ONE);
1204
+ });
1205
+
1206
+ // _integerAdd: integer-pyretnum integer-pyretnum -> integer-pyretnum
1207
+ var _integerAdd = makeIntegerBinop(
1208
+ function(m, n) {
1209
+ return m + n;
1210
+ },
1211
+ function(m, n) {
1212
+ return bnAdd.call(m, n);
1213
+ });
1214
+
1215
+ // _integerSubtract: integer-pyretnum integer-pyretnum -> integer-pyretnum
1216
+ var _integerSubtract = makeIntegerBinop(
1217
+ function(m, n) {
1218
+ return m - n;
1219
+ },
1220
+ function(m, n) {
1221
+ return bnSubtract.call(m, n);
1222
+ });
1223
+
1224
+ // _integerMultiply: integer-pyretnum integer-pyretnum -> integer-pyretnum
1225
+ var _integerMultiply = makeIntegerBinop(
1226
+ function(m, n) {
1227
+ return m * n;
1228
+ },
1229
+ function(m, n) {
1230
+ return bnMultiply.call(m, n);
1231
+ });
1232
+
1233
+ //_integerQuotient: integer-pyretnum integer-pyretnum -> integer-pyretnum
1234
+ var _integerQuotient = makeIntegerBinop(
1235
+ function(m, n) {
1236
+ return ((m - (m % n))/ n);
1237
+ },
1238
+ function(m, n) {
1239
+ return bnDivide.call(m, n);
1240
+ });
1241
+
1242
+ var _integerRemainder = makeIntegerBinop(
1243
+ function(m, n) {
1244
+ return m % n;
1245
+ },
1246
+ function(m, n) {
1247
+ return bnRemainder.call(m, n);
1248
+ });
1249
+
1250
+ // splitIntIntoMantissaExpt: integer-pyretnum -> [JS-double, JS-int]
1251
+ //
1252
+ // splitIntIntoMantissaExpt takes an integer s (either unboxed or BigInteger)
1253
+ // and returns [mantissa, exponent]
1254
+ // such that s ~= mantissa * 10^exponent.
1255
+ // mantissa is a JS-double, and is chosen to have one non-zero digit
1256
+ // to the left of the decimal point.
1257
+ // Because mantissa is a JS-double, there is in general a loss of precision.
1258
+ // splitIntIntoMantissaExpt is used to create a best-possible JS-double version
1259
+ // of its argument arbitrarily precise integer.
1260
+ // E.g., splitIntIntoMantissaExpt(256) returns
1261
+ // [2.56, 2]
1262
+ // splitIntIntoMantissaExpt(111222333444555666777888999) returns
1263
+ // [1.1122233344455567, 26]
1264
+ //
1265
+ var splitIntIntoMantissaExpt = function(s) {
1266
+ var str = s.toString();
1267
+ var c0 = str[0];
1268
+ var sign = '';
1269
+
1270
+ if (c0 === '-' || c0 === '+') {
1271
+ str = str.substring(1);
1272
+ if (c0 === '-') {
1273
+ sign = '-';
1274
+ }
1275
+ }
1276
+
1277
+ var d0 = str[0];
1278
+ str = str.substring(1);
1279
+
1280
+ var mantissa = Number(sign + d0 + '.' + str);
1281
+ var expt = str.length;
1282
+
1283
+ return [mantissa, expt];
1284
+ };
1285
+
1286
+ // _integerDivideToFixnum: integer-pyretnum integer-pyretnum -> fixnum
1287
+ //
1288
+ // _integerDivideToFixnum takes two integers (possibly BigIntegers) and
1289
+ // returns the best fixnum representing their quotient.
1290
+ // If the args are both JS-doubles, the JS quotient is returned if it
1291
+ // doesn't overflow.
1292
+ // If it does overflow, or if at least one of the args is a BigInt, then
1293
+ // splitIntIntoMantissaExpt is used to convert the args to
1294
+ // [mantissa, exponent] form. The result a*10^b, where
1295
+ // a = the mantissae's quotient, and
1296
+ // b = the exponents' difference
1297
+ //
1298
+ var _integerDivideToFixnum = makeIntegerBinop(
1299
+ function(m, n) {
1300
+ return m / n;
1301
+ },
1302
+ function(m, n) {
1303
+ var xm = splitIntIntoMantissaExpt(m);
1304
+ var xn = splitIntIntoMantissaExpt(n);
1305
+ var r = Number(String(xm[0] / xn[0]) + 'e' +
1306
+ String(xm[1] - xn[1]));
1307
+ return r;
1308
+ },
1309
+ { ignoreOverflow: false,
1310
+ doNotCoerceToFloating: true
1311
+ }
1312
+ );
1313
+
1314
+ // _integerEquals: integer-pyretnum integer-pyretnum -> boolean
1315
+ var _integerEquals = makeIntegerBinop(
1316
+ function(m, n) {
1317
+ return m === n;
1318
+ },
1319
+ function(m, n) {
1320
+ return bnEquals.call(m, n);
1321
+ },
1322
+ {doNotCoerceToFloating: true});
1323
+
1324
+ // _integerGreaterThan: integer-pyretnum integer-pyretnum -> boolean
1325
+ var _integerGreaterThan = makeIntegerBinop(
1326
+ function(m, n) {
1327
+ return m > n;
1328
+ },
1329
+ function(m, n) {
1330
+ return bnCompareTo.call(m, n) > 0;
1331
+ },
1332
+ {doNotCoerceToFloating: true});
1333
+
1334
+ // _integerLessThan: integer-pyretnum integer-pyretnum -> boolean
1335
+ var _integerLessThan = makeIntegerBinop(
1336
+ function(m, n) {
1337
+ return m < n;
1338
+ },
1339
+ function(m, n) {
1340
+ return bnCompareTo.call(m, n) < 0;
1341
+ },
1342
+ {doNotCoerceToFloating: true});
1343
+
1344
+ // _integerGreaterThanOrEqual: integer-pyretnum integer-pyretnum -> boolean
1345
+ var _integerGreaterThanOrEqual = makeIntegerBinop(
1346
+ function(m, n) {
1347
+ return m >= n;
1348
+ },
1349
+ function(m, n) {
1350
+ return bnCompareTo.call(m, n) >= 0;
1351
+ },
1352
+ {doNotCoerceToFloating: true});
1353
+
1354
+ // _integerLessThanOrEqual: integer-pyretnum integer-pyretnum -> boolean
1355
+ var _integerLessThanOrEqual = makeIntegerBinop(
1356
+ function(m, n) {
1357
+ return m <= n;
1358
+ },
1359
+ function(m, n) {
1360
+ return bnCompareTo.call(m, n) <= 0;
1361
+ },
1362
+ {doNotCoerceToFloating: true});
1363
+
1364
+ //////////////////////////////////////////////////////////////////////
1365
+ // The boxed number types are expected to implement the following
1366
+ // interface.
1367
+ //
1368
+ // toString: -> string
1369
+
1370
+ // isFinite: -> boolean
1371
+
1372
+ // isInteger: -> boolean
1373
+ // Produce true if this number can be coerced into an integer.
1374
+
1375
+ // isRational: -> boolean
1376
+ // Produce true if the number is rational.
1377
+
1378
+ // isExact === isRational
1379
+
1380
+ // isReal: -> boolean
1381
+ // Produce true if the number is real.
1382
+
1383
+ // toRational: -> pyretnum
1384
+ // Produce an exact number.
1385
+
1386
+ // toExact === toRational
1387
+
1388
+ // toRoughnum: -> pyretnum
1389
+ // Produce a roughnum.
1390
+
1391
+ // toFixnum: -> fixnum
1392
+ // Produce a javascript number.
1393
+
1394
+ // greaterThan: pyretnum -> boolean
1395
+ // Compare against instance of the same type.
1396
+
1397
+ // greaterThanOrEqual: pyretnum -> boolean
1398
+ // Compare against instance of the same type.
1399
+
1400
+ // lessThan: pyretnum -> boolean
1401
+ // Compare against instance of the same type.
1402
+
1403
+ // lessThanOrEqual: pyretnum -> boolean
1404
+ // Compare against instance of the same type.
1405
+
1406
+ // add: pyretnum -> pyretnum
1407
+ // Add with an instance of the same type.
1408
+
1409
+ // subtract: pyretnum -> pyretnum
1410
+ // Subtract with an instance of the same type.
1411
+
1412
+ // multiply: pyretnum -> pyretnum
1413
+ // Multiply with an instance of the same type.
1414
+
1415
+ // divide: pyretnum -> pyretnum
1416
+ // Divide with an instance of the same type.
1417
+
1418
+ // numerator: -> pyretnum
1419
+ // Return the numerator.
1420
+
1421
+ // denominator: -> pyretnum
1422
+ // Return the denominator.
1423
+
1424
+ // integerSqrt: -> pyretnum
1425
+ // Produce the integer square root.
1426
+
1427
+ // sqrt: -> pyretnum
1428
+ // Produce the square root.
1429
+
1430
+ // abs: -> pyretnum
1431
+ // Produce the absolute value.
1432
+
1433
+ // floor: -> pyretnum
1434
+ // Produce the floor.
1435
+
1436
+ // ceiling: -> pyretnum
1437
+ // Produce the ceiling.
1438
+
1439
+ // log: -> pyretnum
1440
+ // Produce the log.
1441
+
1442
+ // atan: -> pyretnum
1443
+ // Produce the arc tangent.
1444
+
1445
+ // cos: -> pyretnum
1446
+ // Produce the cosine.
1447
+
1448
+ // sin: -> pyretnum
1449
+ // Produce the sine.
1450
+
1451
+ // expt: pyretnum -> pyretnum
1452
+ // Produce the power to the input.
1453
+
1454
+ // exp: -> pyretnum
1455
+ // Produce e raised to the given power.
1456
+
1457
+ // acos: -> pyretnum
1458
+ // Produce the arc cosine.
1459
+
1460
+ // asin: -> pyretnum
1461
+ // Produce the arc sine.
1462
+
1463
+ // round: -> pyretnum
1464
+ // Round to the nearest integer.
1465
+
1466
+ // equals: pyretnum -> boolean
1467
+ // Produce true if the given number of the same type is equal.
1468
+
1469
+ //////////////////////////////////////////////////////////////////////
1470
+
1471
+ // Rationals
1472
+
1473
+ var Rational = function(n, d) {
1474
+ this.n = n;
1475
+ this.d = d;
1476
+ };
1477
+
1478
+ Rational.makeInstance = function(n, d) {
1479
+ if (n === undefined)
1480
+ errbacks.throwUndefinedValue("n undefined", n, d);
1481
+
1482
+ if (d === undefined) { d = 1; }
1483
+
1484
+ if (_integerLessThan(d, 0)) {
1485
+ n = negate(n);
1486
+ d = negate(d);
1487
+ }
1488
+
1489
+ var divisor = _integerGcd(abs(n), abs(d));
1490
+ n = _integerQuotient(n, divisor);
1491
+ d = _integerQuotient(d, divisor);
1492
+
1493
+ // Optimization: if we can get around construction the rational
1494
+ // in favor of just returning n, do it:
1495
+ if (_integerIsOne(d) || _integerIsZero(n)) {
1496
+ return n;
1497
+ }
1498
+
1499
+ return new Rational(n, d);
1500
+ };
1501
+
1502
+ Rational.prototype.toString = function() {
1503
+ if (_integerIsOne(this.d)) {
1504
+ return this.n.toString() + "";
1505
+ } else {
1506
+ return this.n.toString() + "/" + this.d.toString();
1507
+ }
1508
+ };
1509
+
1510
+ Rational.prototype.isFinite = function() {
1511
+ return true;
1512
+ };
1513
+
1514
+ Rational.prototype.equals = function(other) {
1515
+ return (other instanceof Rational &&
1516
+ _integerEquals(this.n, other.n) &&
1517
+ _integerEquals(this.d, other.d));
1518
+ };
1519
+
1520
+ Rational.prototype.isInteger = function() {
1521
+ return _integerIsOne(this.d);
1522
+ };
1523
+
1524
+ Rational.prototype.isRational = function() {
1525
+ return true;
1526
+ };
1527
+
1528
+ Rational.prototype.isExact = Rational.prototype.isRational;
1529
+
1530
+ Rational.prototype.isReal = function() {
1531
+ return true;
1532
+ };
1533
+
1534
+ Rational.prototype.isRoughnum = function() {
1535
+ return false;
1536
+ };
1537
+
1538
+ Rational.prototype.isPositive = function() {
1539
+ // don't care about this.d
1540
+ return this.n > 0;
1541
+ };
1542
+
1543
+ Rational.prototype.isNonNegative = function() {
1544
+ return this.n >= 0;
1545
+ };
1546
+
1547
+ Rational.prototype.isNegative = function() {
1548
+ return this.n < 0;
1549
+ };
1550
+
1551
+ Rational.prototype.isNonPositive = function() {
1552
+ return this.n <= 0;
1553
+ };
1554
+
1555
+ Rational.prototype.add = function(other) {
1556
+ return Rational.makeInstance(_integerAdd(_integerMultiply(this.n, other.d),
1557
+ _integerMultiply(this.d, other.n)),
1558
+ _integerMultiply(this.d, other.d));
1559
+ };
1560
+
1561
+ Rational.prototype.subtract = function(other) {
1562
+ return Rational.makeInstance(_integerSubtract(_integerMultiply(this.n, other.d),
1563
+ _integerMultiply(this.d, other.n)),
1564
+ _integerMultiply(this.d, other.d));
1565
+ };
1566
+
1567
+ Rational.prototype.negate = function() {
1568
+ return Rational.makeInstance(negate(this.n), this.d)
1569
+ };
1570
+
1571
+ Rational.prototype.multiply = function(other) {
1572
+ return Rational.makeInstance(_integerMultiply(this.n, other.n),
1573
+ _integerMultiply(this.d, other.d));
1574
+ };
1575
+
1576
+ Rational.prototype.divide = function(other) {
1577
+ if (_integerIsZero(this.d) || _integerIsZero(other.n)) { // dead code!
1578
+ errbacks.throwDivByZero("/: division by zero", this, other);
1579
+ }
1580
+ return Rational.makeInstance(_integerMultiply(this.n, other.d),
1581
+ _integerMultiply(this.d, other.n));
1582
+ };
1583
+
1584
+ Rational.prototype.toRational = function() {
1585
+ return this;
1586
+ };
1587
+
1588
+ Rational.prototype.toExact = Rational.prototype.toRational;
1589
+
1590
+
1591
+ Rational.prototype.toFixnum = function() {
1592
+ return _integerDivideToFixnum(this.n, this.d);
1593
+ };
1594
+
1595
+ Rational.prototype.toRoughnum = function() {
1596
+ return Roughnum.makeInstance(this.toFixnum());
1597
+ };
1598
+
1599
+ Rational.prototype.numerator = function() {
1600
+ return this.n;
1601
+ };
1602
+
1603
+ Rational.prototype.denominator = function() {
1604
+ return this.d;
1605
+ };
1606
+
1607
+ Rational.prototype.greaterThan = function(other) {
1608
+ return _integerGreaterThan(_integerMultiply(this.n, other.d),
1609
+ _integerMultiply(this.d, other.n));
1610
+ };
1611
+
1612
+ Rational.prototype.greaterThanOrEqual = function(other) {
1613
+ return _integerGreaterThanOrEqual(_integerMultiply(this.n, other.d),
1614
+ _integerMultiply(this.d, other.n));
1615
+ };
1616
+
1617
+ Rational.prototype.lessThan = function(other) {
1618
+ return _integerLessThan(_integerMultiply(this.n, other.d),
1619
+ _integerMultiply(this.d, other.n));
1620
+ };
1621
+
1622
+ Rational.prototype.lessThanOrEqual = function(other) {
1623
+ return _integerLessThanOrEqual(_integerMultiply(this.n, other.d),
1624
+ _integerMultiply(this.d, other.n));
1625
+ };
1626
+
1627
+ Rational.prototype.integerSqrt = function() {
1628
+ var result = sqrt(this);
1629
+ return toRational(floor(result));
1630
+ };
1631
+
1632
+ Rational.prototype.sqrt = function() {
1633
+ var newN = sqrt(this.n);
1634
+ var newD = sqrt(this.d);
1635
+ if (isRational(newN) && isRational(newD) &&
1636
+ equals(floor(newN), newN) &&
1637
+ equals(floor(newD), newD)) {
1638
+ return Rational.makeInstance(newN, newD);
1639
+ } else {
1640
+ return divide(newN, newD);
1641
+ }
1642
+ };
1643
+
1644
+ Rational.prototype.abs = function() {
1645
+ return Rational.makeInstance(abs(this.n),
1646
+ this.d);
1647
+ };
1648
+
1649
+ Rational.prototype.floor = function() {
1650
+ var quotient = _integerQuotient(this.n, this.d);
1651
+ if (_integerLessThan(this.n, 0)) {
1652
+ return subtract(quotient, 1);
1653
+ } else {
1654
+ return quotient;
1655
+ }
1656
+ };
1657
+
1658
+ Rational.prototype.ceiling = function() {
1659
+ var quotient = _integerQuotient(this.n, this.d);
1660
+ if (_integerLessThan(this.n, 0)) {
1661
+ return quotient;
1662
+ } else {
1663
+ return add(quotient, 1);
1664
+ }
1665
+ };
1666
+
1667
+ Rational.prototype.round = function() {
1668
+ var halfintp = equals(this.d, 2);
1669
+ var negativep = _integerLessThan(this.n, 0);
1670
+ var n = this.n;
1671
+ if (negativep) {
1672
+ n = negate(n);
1673
+ }
1674
+ var quo = _integerQuotient(n, this.d);
1675
+ if (halfintp) {
1676
+ // rounding half to away from 0
1677
+ // uncomment following if rounding half to even
1678
+ // if (_integerIsOne(_integerModulo(quo, 2)))
1679
+ quo = add(quo, 1);
1680
+ } else {
1681
+ var rem = _integerRemainder(n, this.d);
1682
+ if (greaterThan(multiply(rem, 2), this.d)) {
1683
+ quo = add(quo, 1);
1684
+ }
1685
+ }
1686
+ if (negativep) {
1687
+ quo = negate(quo);
1688
+ }
1689
+ return quo;
1690
+ };
1691
+
1692
+ Rational.prototype.roundEven = function() {
1693
+ // rounds half-integers to even
1694
+ var halfintp = equals(this.d, 2);
1695
+ var negativep = _integerLessThan(this.n, 0);
1696
+ var n = this.n;
1697
+ if (negativep) n = negate(n);
1698
+ var quo = _integerQuotient(n, this.d);
1699
+ if (halfintp) {
1700
+ if (_integerIsOne(_integerModulo(quo, 2)))
1701
+ quo = add(quo, 1);
1702
+ } else {
1703
+ var rem = _integerRemainder(n, this.d);
1704
+ if (greaterThan(multiply(rem, 2), this.d))
1705
+ quo = add(quo, 1);
1706
+ }
1707
+ if (negativep) quo = negate(quo);
1708
+ return quo;
1709
+ };
1710
+
1711
+ Rational.prototype.log = function(){
1712
+ return log(this)
1713
+ };
1714
+
1715
+ Rational.prototype.tan = function(){
1716
+ return Roughnum.makeInstance(Math.tan(this.toFixnum()));
1717
+ };
1718
+
1719
+ Rational.prototype.atan = function(){
1720
+ return Roughnum.makeInstance(Math.atan(this.toFixnum()));
1721
+ };
1722
+
1723
+ Rational.prototype.cos = function(){
1724
+ return Roughnum.makeInstance(Math.cos(this.toFixnum()));
1725
+ };
1726
+
1727
+ Rational.prototype.sin = function(){
1728
+ return Roughnum.makeInstance(Math.sin(this.toFixnum()));
1729
+ };
1730
+
1731
+ var integerNthRoot = function(n, m) {
1732
+ if (sign(n) < 0)
1733
+ errbacks.throwDomainError('integerNthRoot: root ' + n + ' is negative.');
1734
+ if (sign(m) < 0)
1735
+ errbacks.throwDomainError('integerNthRoot: radicand ' + m + ' is negative.');
1736
+ var guessPrev, guessToTheN;
1737
+ var guess = floor(m);
1738
+
1739
+ // find closest integral zero of x^n - m = 0 using Newton-Raphson.
1740
+ // if k'th guess is x_k, then
1741
+ // x_{k+1} = floor( x_k - [(x_k)^n - m]/[n (x_k)^(n-1)] ).
1742
+ // Stop iteration if (x_k)^n is close enough to m, or
1743
+ // if x_k stops evolving
1744
+
1745
+ while(true) {
1746
+ guessToTheN = expt(guess, n);
1747
+ if (lessThanOrEqual(guessToTheN, m) &&
1748
+ lessThan(m, expt(add(guess, 1), n))) break;
1749
+ guessPrev = guess;
1750
+ guess = floor(subtract(guess, divide(subtract(guessToTheN, m),
1751
+ multiply(n, divide(guessToTheN, guess)))));
1752
+ if (equals(guess, guessPrev)) break;
1753
+ }
1754
+
1755
+ return guess;
1756
+ };
1757
+
1758
+ var nthRoot = function(n, m) {
1759
+ var mNeg = (sign(m) < 0);
1760
+ var mAbs = (mNeg ? abs(m) : m);
1761
+ var approx;
1762
+
1763
+ if (mNeg && _integerModulo(n, 2) === 0)
1764
+ errbacks.throwDomainError('expt: taking even (' + n + ') root of negative integer ' + m);
1765
+
1766
+ approx = integerNthRoot(n, mAbs);
1767
+ if (mNeg) approx = negate(approx);
1768
+ if (eqv(expt(approx, n), m)) return approx;
1769
+
1770
+ approx = Roughnum.makeInstance(Math.pow(toFixnum(mAbs),
1771
+ toFixnum(divide(1,n))));
1772
+ return (mNeg ? negate(approx) : approx);
1773
+ };
1774
+
1775
+ Rational.prototype.expt = function(a) {
1776
+ if (isInteger(a) && greaterThanOrEqual(a, 0)) {
1777
+ return fastExpt(this, a);
1778
+ } else if (_integerLessThanOrEqual(a.d, 8)) {
1779
+ var nRaisedToAn = expt(this.n, a.n);
1780
+ var dRaisedToAn = expt(this.d, a.n);
1781
+ var newN = nthRoot(a.d, nRaisedToAn);
1782
+ var newD = nthRoot(a.d, dRaisedToAn);
1783
+ if (isRational(newN) && isRational(newD) &&
1784
+ equals(floor(newN), newN) &&
1785
+ equals(floor(newD), newD)) {
1786
+ return Rational.makeInstance(newN, newD);
1787
+ } else {
1788
+ return divide(newN, newD);
1789
+ }
1790
+ } else {
1791
+ if (this.isNegative() && !a.isInteger())
1792
+ errbacks.throwDomainError('expt: raising negative number ' + this + ' to nonintegral power ' + a);
1793
+ return Roughnum.makeInstance(Math.pow(this.toFixnum(), a.toFixnum()));
1794
+ }
1795
+ };
1796
+
1797
+ Rational.prototype.exp = function(){
1798
+ var res = Math.exp(this.toFixnum());
1799
+ if (!isFinite(res))
1800
+ errbacks.throwDomainError('exp: argument too large: ' + this);
1801
+ return Roughnum.makeInstance(res);
1802
+ };
1803
+
1804
+ Rational.prototype.acos = function(){
1805
+ return acos(this.toFixnum());
1806
+ };
1807
+
1808
+ Rational.prototype.asin = function(){
1809
+ return asin(this.toFixnum());
1810
+ };
1811
+
1812
+ // sign: Number -> {-1, 0, 1}
1813
+ var sign = function(n) {
1814
+ if (lessThan(n, 0)) {
1815
+ return -1;
1816
+ } else if (greaterThan(n, 0)) {
1817
+ return 1;
1818
+ } else {
1819
+ return 0;
1820
+ }
1821
+ };
1822
+
1823
+ // Roughnums
1824
+
1825
+ var Roughnum = function(n) {
1826
+ if (!(typeof(n) === 'number'))
1827
+ errbacks.throwGeneralError('roughnum constructor got unsuitable arg ' + n);
1828
+ this.n = n;
1829
+ };
1830
+
1831
+ Roughnum.makeInstance = function(n) {
1832
+ if (typeof(n) === 'number' && !isFinite(n)) {
1833
+ errbacks.throwDomainError('roughnum overflow error');
1834
+ }
1835
+ return new Roughnum(n);
1836
+ };
1837
+
1838
+ Roughnum.prototype.isFinite = function() {
1839
+ //actually always true, as we don't store overflows
1840
+ return (isFinite(this.n));
1841
+ };
1842
+
1843
+ Roughnum.prototype.toRational = function() {
1844
+ if (!isFinite(this.n)) {
1845
+ // this _should_ be dead, as we don't store overflows
1846
+ errbacks.throwInternalError("toRational: no exact representation for " + this);
1847
+ }
1848
+
1849
+ return fromString(this.n.toString());
1850
+ };
1851
+
1852
+ Roughnum.prototype.toExact = Roughnum.prototype.toRational;
1853
+
1854
+ Roughnum.prototype.toString = function() {
1855
+ return '~' + this.n.toString();
1856
+ };
1857
+
1858
+ Roughnum.prototype.equals = function(other) {
1859
+ errbacks.throwIncomparableValues("roughnums cannot be compared for equality");
1860
+ };
1861
+
1862
+ Roughnum.prototype.isRational = function() {
1863
+ return false;
1864
+ };
1865
+
1866
+ Roughnum.prototype.isExact = Roughnum.prototype.isRational;
1867
+
1868
+ Roughnum.prototype.isInteger = function() {
1869
+ return false;
1870
+ };
1871
+
1872
+ Roughnum.prototype.isReal = function() {
1873
+ return true;
1874
+ };
1875
+
1876
+ Roughnum.prototype.isRoughnum = function() {
1877
+ return true;
1878
+ };
1879
+
1880
+ Roughnum.prototype.isPositive = function() {
1881
+ return this.n > 0;
1882
+ };
1883
+
1884
+ Roughnum.prototype.isNonNegative = function() {
1885
+ return this.n >= 0;
1886
+ };
1887
+
1888
+ Roughnum.prototype.isNegative = function() {
1889
+ return this.n < 0;
1890
+ };
1891
+
1892
+ Roughnum.prototype.isNonPositive = function() {
1893
+ return this.n <= 0;
1894
+ };
1895
+
1896
+ Roughnum.prototype.add = function(other) {
1897
+ return Roughnum.makeInstance(this.n + other.n);
1898
+ };
1899
+
1900
+ Roughnum.prototype.subtract = function(other) {
1901
+ return Roughnum.makeInstance(this.n - other.n);
1902
+ };
1903
+
1904
+ Roughnum.prototype.negate = function() {
1905
+ return Roughnum.makeInstance(-this.n);
1906
+ };
1907
+
1908
+ Roughnum.prototype.multiply = function(other) {
1909
+ return Roughnum.makeInstance(this.n * other.n);
1910
+ };
1911
+
1912
+ Roughnum.prototype.divide = function(other) {
1913
+ return Roughnum.makeInstance(this.n / other.n);
1914
+ };
1915
+
1916
+ Roughnum.prototype.toFixnum = function() {
1917
+ return this.n;
1918
+ };
1919
+
1920
+ Roughnum.prototype.toRoughnum = function() {
1921
+ return this;
1922
+ };
1923
+
1924
+ Roughnum.prototype.numerator = function() {
1925
+ var stringRep = this.n.toString();
1926
+ var match = stringRep.match(/^(.*)\.(.*)$/);
1927
+ if (match) {
1928
+ var afterDecimal = parseInt(match[2]);
1929
+ var factorToInt = Math.pow(10, match[2].length);
1930
+ var extraFactor = _integerGcd(factorToInt, afterDecimal);
1931
+ var multFactor = factorToInt / extraFactor;
1932
+ return Roughnum.makeInstance( Math.round(this.n * multFactor) );
1933
+ } else {
1934
+ return this;
1935
+ }
1936
+ };
1937
+
1938
+ Roughnum.prototype.denominator = function() {
1939
+ var stringRep = this.n.toString();
1940
+ var match = stringRep.match(/^(.*)\.(.*)$/);
1941
+ if (match) {
1942
+ var afterDecimal = parseInt(match[2]);
1943
+ var factorToInt = Math.pow(10, match[2].length);
1944
+ var extraFactor = _integerGcd(factorToInt, afterDecimal);
1945
+ return Roughnum.makeInstance( Math.round(factorToInt/extraFactor) );
1946
+ } else {
1947
+ return Roughnum.makeInstance(1);
1948
+ }
1949
+ };
1950
+
1951
+ Roughnum.prototype.floor = function() {
1952
+ return Math.floor(this.n);
1953
+ };
1954
+
1955
+ Roughnum.prototype.ceiling = function() {
1956
+ return Math.ceil(this.n);
1957
+ };
1958
+
1959
+ Roughnum.prototype.round = function(){
1960
+ var negativep = (this.n < 0);
1961
+ var n = this.n;
1962
+ if (negativep) n = -n;
1963
+ var res = Math.round(n);
1964
+ if (negativep) res = -res;
1965
+ return res;
1966
+ };
1967
+
1968
+ Roughnum.prototype.roundEven = function() {
1969
+ var negativep = (this.n < 0);
1970
+ var n = this.n;
1971
+ if (negativep) n = -n;
1972
+ var res = Math.round(n);
1973
+ if ((Math.abs(n - res) === 0.5) && (res % 2 === 1))
1974
+ res -= 1;
1975
+ return res;
1976
+ };
1977
+
1978
+ Roughnum.prototype.greaterThan = function(other) {
1979
+ return this.n > other.n;
1980
+ };
1981
+
1982
+ Roughnum.prototype.greaterThanOrEqual = function(other) {
1983
+ return this.n >= other.n;
1984
+ };
1985
+
1986
+ Roughnum.prototype.lessThan = function(other) {
1987
+ return this.n < other.n;
1988
+ };
1989
+
1990
+ Roughnum.prototype.lessThanOrEqual = function(other) {
1991
+ return this.n <= other.n;
1992
+ };
1993
+
1994
+ Roughnum.prototype.integerSqrt = function() {
1995
+ if (isInteger(this)) {
1996
+ if(this.n >= 0) {
1997
+ return Roughnum.makeInstance(Math.floor(Math.sqrt(this.n)));
1998
+ } else {
1999
+ errbacks.throwDomainError('integerSqrt of negative roughnum', this.n);
2000
+ }
2001
+ } else {
2002
+ errbacks.throwDomainError("integerSqrt: can only be applied to an integer", this);
2003
+ }
2004
+ };
2005
+
2006
+ Roughnum.prototype.sqrt = function() {
2007
+ return Roughnum.makeInstance(Math.sqrt(this.n));
2008
+ };
2009
+
2010
+ Roughnum.prototype.abs = function() {
2011
+ return Roughnum.makeInstance(Math.abs(this.n));
2012
+ };
2013
+
2014
+ Roughnum.prototype.log = function(){
2015
+ if (this.n < 0)
2016
+ errbacks.throwDomainError('log of negative roughnum', this.n);
2017
+ else
2018
+ return Roughnum.makeInstance(Math.log(this.n));
2019
+ };
2020
+
2021
+ Roughnum.prototype.tan = function(){
2022
+ return Roughnum.makeInstance(Math.tan(this.n));
2023
+ };
2024
+
2025
+ Roughnum.prototype.atan = function(){
2026
+ return Roughnum.makeInstance(Math.atan(this.n));
2027
+ };
2028
+
2029
+ Roughnum.prototype.cos = function(){
2030
+ return Roughnum.makeInstance(Math.cos(this.n));
2031
+ };
2032
+
2033
+ Roughnum.prototype.sin = function(){
2034
+ return Roughnum.makeInstance(Math.sin(this.n));
2035
+ };
2036
+
2037
+ Roughnum.prototype.expt = function(a){
2038
+ if (this.n === 1) {
2039
+ return this;
2040
+ } else {
2041
+ return Roughnum.makeInstance(Math.pow(this.n, a.n));
2042
+ }
2043
+ };
2044
+
2045
+ Roughnum.prototype.exp = function(){
2046
+ var res = Math.exp(this.n);
2047
+ if (!isFinite(res))
2048
+ errbacks.throwDomainError('exp: argument too large: ' + this);
2049
+ return Roughnum.makeInstance(res);
2050
+ };
2051
+
2052
+ Roughnum.prototype.acos = function(){
2053
+ return acos(this.n);
2054
+ };
2055
+
2056
+ Roughnum.prototype.asin = function(){
2057
+ return asin(this.n);
2058
+ };
2059
+
2060
+ var rationalRegexp = new RegExp("^([+-]?\\d+)/(\\d+)$");
2061
+ var digitRegexp = new RegExp("^[+-]?\\d+$");
2062
+ var flonumRegexp = new RegExp("^([-+]?)(\\d+\)((?:\\.\\d+)?)((?:[Ee][-+]?\\d+)?)$");
2063
+
2064
+
2065
+ var roughnumDecRegexp = new RegExp("^~([-+]?\\d+(?:\\.\\d+)?(?:[Ee][-+]?\\d+)?)$");
2066
+
2067
+ var roughnumRatRegexp = new RegExp("^~([+-]?\\d+)/(\\d+)$");
2068
+
2069
+ var scientificPattern = new RegExp("^([+-]?\\d*\\.?\\d*)[Ee]([+]?\\d+)$");
2070
+
2071
+ // fromString: string -> (pyretnum | false)
2072
+ var fromString = function(x) {
2073
+ if (x.match(digitRegexp)) {
2074
+ var n = Number(x);
2075
+ if (isOverflow(n)) {
2076
+ return makeBignum(x);
2077
+ } else {
2078
+ return n;
2079
+ }
2080
+ }
2081
+
2082
+ var aMatch = x.match(rationalRegexp);
2083
+ if (aMatch) {
2084
+ return Rational.makeInstance(fromString(aMatch[1]),
2085
+ fromString(aMatch[2]));
2086
+ }
2087
+
2088
+ aMatch = x.match(flonumRegexp);
2089
+ if (aMatch) {
2090
+ var negativeP = (aMatch[1] === "-");
2091
+ //
2092
+ var beforeDecimalString = aMatch[2];
2093
+ var beforeDecimal = 0;
2094
+ if (beforeDecimalString !== '') {
2095
+ beforeDecimal = makeBignum(beforeDecimalString);
2096
+ }
2097
+ //
2098
+ var afterDecimalString = aMatch[3];
2099
+ var denominatorTen = 1;
2100
+ var afterDecimal = 0;
2101
+ if (afterDecimalString !== '') {
2102
+ afterDecimalString = afterDecimalString.substring(1);
2103
+ denominatorTen = makeBignum('1' + new Array(afterDecimalString.length + 1).join('0'));
2104
+ if (afterDecimalString !== '') {
2105
+ afterDecimal = makeBignum(afterDecimalString);
2106
+ }
2107
+ }
2108
+ //
2109
+ var exponentString = aMatch[4];
2110
+ var exponentNegativeP = false;
2111
+ var exponent = 1;
2112
+ if (exponentString !== '') {
2113
+ exponentString = exponentString.substring(1);
2114
+ var exponentSign = exponentString.charAt(0);
2115
+ exponentNegativeP = (exponentSign === '-');
2116
+ if (exponentSign === '-' || exponentSign === '+') {
2117
+ exponentString = exponentString.substring(1);
2118
+ }
2119
+ exponent = makeBignum('1' + new Array(Number(exponentString) + 1).join('0'));
2120
+ }
2121
+
2122
+ var finalDen = denominatorTen;
2123
+ var finalNum = _integerAdd(_integerMultiply(beforeDecimal, denominatorTen),
2124
+ afterDecimal);
2125
+ if (negativeP) {
2126
+ finalNum = negate(finalNum);
2127
+ }
2128
+ //
2129
+ if (!equals(exponent, 1)) {
2130
+ if (exponentNegativeP) {
2131
+ finalDen = _integerMultiply(finalDen, exponent);
2132
+ } else {
2133
+ finalNum = _integerMultiply(finalNum, exponent);
2134
+ }
2135
+ }
2136
+ return Rational.makeInstance(finalNum, finalDen);
2137
+ }
2138
+
2139
+ aMatch = x.match(roughnumRatRegexp);
2140
+ if (aMatch) {
2141
+ return toRoughnum(Rational.makeInstance(fromString(aMatch[1]), fromString(aMatch[2])));
2142
+ }
2143
+
2144
+ aMatch = x.match(roughnumDecRegexp);
2145
+ if (aMatch) {
2146
+ return Roughnum.makeInstance(Number(aMatch[1]));
2147
+ }
2148
+
2149
+ return false; // if all else fails
2150
+
2151
+ };
2152
+
2153
+ ///////////////////////////////////////////////////////////
2154
+
2155
+ // recognizing numbers in (We)Scheme syntax:
2156
+
2157
+ var hashModifiersRegexp = new RegExp("^(#[ei]#[bodx]|#[bodx]#[ei]|#[bodxei])(.*)$")
2158
+
2159
+ function schemeRationalRegexp(digits) { return new RegExp("^([+-]?["+digits+"]+)/(["+digits+"]+)$"); }
2160
+
2161
+ function matchComplexRegexp(radix, x) {
2162
+ var sign = "[+-]";
2163
+ var maybeSign = "[+-]?";
2164
+ var digits = digitsForRadix(radix)
2165
+ var expmark = "["+expMarkForRadix(radix)+"]"
2166
+ var digitSequence = "["+digits+"]+"
2167
+
2168
+ var unsignedRational = digitSequence+"/"+digitSequence
2169
+ var rational = maybeSign + unsignedRational
2170
+
2171
+ var noDecimal = digitSequence
2172
+ var decimalNumOnRight = "["+digits+"]*\\.["+digits+"]+"
2173
+ var decimalNumOnLeft = "["+digits+"]+\\.["+digits+"]*"
2174
+
2175
+ var unsignedDecimal = "(?:" + noDecimal + "|" + decimalNumOnRight + "|" + decimalNumOnLeft + ")"
2176
+
2177
+ var special = "(?:inf\.0|nan\.0|inf\.f|nan\.f)"
2178
+
2179
+ var unsignedRealNoExp = "(?:" + unsignedDecimal + "|" + unsignedRational + ")"
2180
+ var unsignedReal = unsignedRealNoExp + "(?:" + expmark + maybeSign + digitSequence + ")?"
2181
+ var unsignedRealOrSpecial = "(?:" + unsignedReal + "|" + special + ")"
2182
+ var real = "(?:" + maybeSign + unsignedReal + "|" + sign + special + ")"
2183
+
2184
+ var alt1 = new RegExp("^(" + rational + ")"
2185
+ + "(" + sign + unsignedRational + "?)"
2186
+ + "i$");
2187
+ var alt2 = new RegExp("^(" + real + ")?"
2188
+ + "(" + sign + unsignedRealOrSpecial + "?)"
2189
+ + "i$");
2190
+ var alt3 = new RegExp("^(" + real + ")@(" + real + ")$");
2191
+
2192
+ var match1 = x.match(alt1)
2193
+ var match2 = x.match(alt2)
2194
+ var match3 = x.match(alt3)
2195
+
2196
+ return match1 ? match1 :
2197
+ match2 ? match2 :
2198
+ match3 ? match3 :
2199
+ /* else */ false
2200
+ }
2201
+
2202
+ function schemeDigitRegexp(digits) { return new RegExp("^[+-]?["+digits+"]+$"); }
2203
+ /**
2204
+ /* NB: !!!! flonum regexp only matches "X.", ".X", or "X.X", NOT "X", this
2205
+ /* must be separately checked with schemeDigitRegexp.
2206
+ /* I know this seems dumb, but the alternative would be that this regexp
2207
+ /* returns six matches, which also seems dumb.
2208
+ /***/
2209
+ function schemeFlonumRegexp(digits) {
2210
+ var decimalNumOnRight = "(["+digits+"]*)\\.(["+digits+"]+)"
2211
+ var decimalNumOnLeft = "(["+digits+"]+)\\.(["+digits+"]*)"
2212
+ return new RegExp("^(?:([+-]?)(" +
2213
+ decimalNumOnRight+"|"+decimalNumOnLeft +
2214
+ "))$");
2215
+ }
2216
+ function schemeScientificPattern(digits, exp_mark) {
2217
+ var noDecimal = "["+digits+"]+"
2218
+ var decimalNumOnRight = "["+digits+"]*\\.["+digits+"]+"
2219
+ var decimalNumOnLeft = "["+digits+"]+\\.["+digits+"]*"
2220
+ return new RegExp("^(?:([+-]?" +
2221
+ "(?:"+noDecimal+"|"+decimalNumOnRight+"|"+decimalNumOnLeft+")" +
2222
+ ")["+exp_mark+"]([+-]?["+digits+"]+))$");
2223
+ }
2224
+
2225
+ function digitsForRadix(radix) {
2226
+ return radix === 2 ? "01" :
2227
+ radix === 8 ? "0-7" :
2228
+ radix === 10 ? "0-9" :
2229
+ radix === 16 ? "0-9a-fA-F" :
2230
+ errbacks.throwInternalError("digitsForRadix: invalid radix", this, radix)
2231
+ }
2232
+ function expMarkForRadix(radix) {
2233
+ return (radix === 2 || radix === 8 || radix === 10) ? "defsl" :
2234
+ (radix === 16) ? "sl" :
2235
+ errbacks.throwInternalError("expMarkForRadix: invalid radix", this, radix)
2236
+ }
2237
+
2238
+ function Exactness(i) {
2239
+ this.defaultp = function () { return i == 0; }
2240
+ this.exactp = function () { return i == 1; }
2241
+ this.inexactp = function () { return i == 2; }
2242
+ }
2243
+
2244
+ Exactness.def = new Exactness(0);
2245
+ Exactness.on = new Exactness(1);
2246
+ Exactness.off = new Exactness(2);
2247
+
2248
+ Exactness.prototype.intAsExactp = function () { return this.defaultp() || this.exactp(); };
2249
+ Exactness.prototype.floatAsInexactp = function () { return this.defaultp() || this.inexactp(); };
2250
+
2251
+ // fromSchemeString: string boolean -> (scheme-number | false)
2252
+ var fromSchemeString = function(x, exactness) {
2253
+
2254
+ var radix = 10
2255
+ var exactness = typeof exactness === 'undefined' ? Exactness.def :
2256
+ exactness === true ? Exactness.on :
2257
+ exactness === false ? Exactness.off :
2258
+ /* else */ errbacks.throwInternalError( "exactness must be true or false"
2259
+ , this
2260
+ , r) ;
2261
+
2262
+ var hMatch = x.toLowerCase().match(hashModifiersRegexp)
2263
+ if (hMatch) {
2264
+ var modifierString = hMatch[1].toLowerCase();
2265
+
2266
+ var exactFlag = modifierString.match(new RegExp("(#[ei])"))
2267
+ var radixFlag = modifierString.match(new RegExp("(#[bodx])"))
2268
+
2269
+ if (exactFlag) {
2270
+ var f = exactFlag[1].charAt(1)
2271
+ exactness = f === 'e' ? Exactness.on :
2272
+ f === 'i' ? Exactness.off :
2273
+ // this case is unreachable
2274
+ errbacks.throwInternalError("invalid exactness flag", this, r)
2275
+ }
2276
+ if (radixFlag) {
2277
+ var f = radixFlag[1].charAt(1)
2278
+ radix = f === 'b' ? 2 :
2279
+ f === 'o' ? 8 :
2280
+ f === 'd' ? 10 :
2281
+ f === 'x' ? 16 :
2282
+ // this case is unreachable
2283
+ errbacks.throwInternalError("invalid radix flag", this, r)
2284
+ }
2285
+ }
2286
+
2287
+ var numberString = hMatch ? hMatch[2] : x
2288
+ // if the string begins with a hash modifier, then it must parse as a
2289
+ // number, an invalid parse is an error, not false. False is returned
2290
+ // when the item could potentially have been read as a symbol.
2291
+ var mustBeANumberp = hMatch ? true : false
2292
+
2293
+ return fromSchemeStringRaw(numberString, radix, exactness, mustBeANumberp)
2294
+ };
2295
+
2296
+ function fromSchemeStringRaw(x, radix, exactness, mustBeANumberp) {
2297
+ var cMatch = matchComplexRegexp(radix, x);
2298
+ if (cMatch) {
2299
+ throw "Complex Numbers are not supported in Pyret";
2300
+ }
2301
+
2302
+ return fromSchemeStringRawNoComplex(x, radix, exactness, mustBeANumberp)
2303
+ }
2304
+
2305
+ function fromSchemeStringRawNoComplex(x, radix, exactness, mustBeANumberp) {
2306
+ var aMatch = x.match(schemeRationalRegexp(digitsForRadix(radix)));
2307
+ if (aMatch) {
2308
+ return Rational.makeInstance( fromSchemeStringRawNoComplex( aMatch[1]
2309
+ , radix
2310
+ , exactness
2311
+ )
2312
+ , fromSchemeStringRawNoComplex( aMatch[2]
2313
+ , radix
2314
+ , exactness
2315
+ )
2316
+ );
2317
+ }
2318
+
2319
+ if (x === '+nan.0' ||
2320
+ x === '-nan.0' ||
2321
+ x === '+inf.0' ||
2322
+ x === '-inf.0' ||
2323
+ x === '-0.0') {
2324
+ return Roughnum.makeInstance(Infinity);
2325
+ }
2326
+
2327
+ var fMatch = x.match(schemeFlonumRegexp(digitsForRadix(radix)))
2328
+ if (fMatch) {
2329
+ var integralPart = fMatch[3] !== undefined ? fMatch[3] : fMatch[5];
2330
+ var fractionalPart = fMatch[4] !== undefined ? fMatch[4] : fMatch[6];
2331
+ return parseFloat( fMatch[1]
2332
+ , integralPart
2333
+ , fractionalPart
2334
+ , radix
2335
+ , exactness
2336
+ )
2337
+ }
2338
+
2339
+ var sMatch = x.match(schemeScientificPattern( digitsForRadix(radix)
2340
+ , expMarkForRadix(radix)
2341
+ ))
2342
+ if (sMatch) {
2343
+ var coefficient = fromSchemeStringRawNoComplex(sMatch[1], radix, exactness)
2344
+ var exponent = fromSchemeStringRawNoComplex(sMatch[2], radix, exactness)
2345
+ return multiply(coefficient, expt(radix, exponent));
2346
+ }
2347
+
2348
+ // Finally, integer tests.
2349
+ if (x.match(schemeDigitRegexp(digitsForRadix(radix)))) {
2350
+ var n = parseInt(x, radix);
2351
+ if (isOverflow(n)) {
2352
+ return makeBignum(x);
2353
+ } else if (exactness.intAsExactp()) {
2354
+ return n;
2355
+ } else {
2356
+ return Roughnum.makeInstance(n)
2357
+ }
2358
+ } else if (mustBeANumberp) {
2359
+ if(x.length===0) errbacks.throwGeneralError("no digits");
2360
+ errbacks.throwGeneralError("bad number: " + x, this);
2361
+ } else {
2362
+ return false;
2363
+ }
2364
+ };
2365
+
2366
+ function parseFloat(sign, integralPart, fractionalPart, radix, exactness) {
2367
+ var sign = (sign == "-" ? -1 : 1);
2368
+ var integralPartValue = integralPart === "" ? 0 :
2369
+ exactness.intAsExactp() ? parseExactInt(integralPart, radix) :
2370
+ parseInt(integralPart, radix)
2371
+
2372
+ var fractionalNumerator = fractionalPart === "" ? 0 :
2373
+ exactness.intAsExactp() ? parseExactInt(fractionalPart, radix) :
2374
+ parseInt(fractionalPart, radix)
2375
+ /* unfortunately, for these next two calculations, `expt` and `divide` */
2376
+ /* will promote to Bignum and Rational, respectively, but we only want */
2377
+ /* these if we're parsing in exact mode */
2378
+ var fractionalDenominator = exactness.intAsExactp() ? expt(radix, fractionalPart.length) :
2379
+ Math.pow(radix, fractionalPart.length)
2380
+ var fractionalPartValue = fractionalPart === "" ? 0 :
2381
+ exactness.intAsExactp() ? divide(fractionalNumerator, fractionalDenominator) :
2382
+ fractionalNumerator / fractionalDenominator
2383
+
2384
+ var forceInexact = function(o) {
2385
+ return typeof o === "number" ? Roughnum.makeInstance(o) :
2386
+ o.toRoughnum();
2387
+ }
2388
+
2389
+ return exactness.floatAsInexactp() ? forceInexact(multiply(sign, add( integralPartValue, fractionalPartValue))) :
2390
+ multiply(sign, add(integralPartValue, fractionalPartValue));
2391
+ }
2392
+
2393
+ function parseExactInt(str, radix) {
2394
+ return fromSchemeStringRawNoComplex(str, radix, Exactness.on, true);
2395
+ }
2396
+
2397
+ //////////////////////////////////////////////////////////////////////
2398
+ //////////////////////////////////////////////////////////////////////
2399
+ //////////////////////////////////////////////////////////////////////
2400
+ //////////////////////////////////////////////////////////////////////
2401
+ //////////////////////////////////////////////////////////////////////
2402
+
2403
+ // The code below comes from Tom Wu's BigInteger implementation:
2404
+
2405
+ // Copyright (c) 2005 Tom Wu
2406
+ // All Rights Reserved.
2407
+ // See "LICENSE" for details.
2408
+
2409
+ // Basic JavaScript BN library - subset useful for RSA encryption.
2410
+
2411
+ // Bits per digit
2412
+ var dbits;
2413
+
2414
+ // JavaScript engine analysis
2415
+ var canary = 0xdeadbeefcafe;
2416
+ var j_lm = ((canary&0xffffff)==0xefcafe);
2417
+
2418
+ // (public) Constructor
2419
+ function BigInteger(a,b,c) {
2420
+ if(a != null)
2421
+ if("number" == typeof a) this.fromNumber(a,b,c);
2422
+ else if(b == null && "string" != typeof a) this.fromString(a,256);
2423
+ else this.fromString(a,b);
2424
+ }
2425
+
2426
+ // return new, unset BigInteger
2427
+ function nbi() { return new BigInteger(null); }
2428
+
2429
+ // am: Compute w_j += (x*this_i), propagate carries,
2430
+ // c is initial carry, returns final carry.
2431
+ // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
2432
+ // We need to select the fastest one that works in this environment.
2433
+
2434
+ // am1: use a single mult and divide to get the high bits,
2435
+ // max digit bits should be 26 because
2436
+ // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
2437
+ function am1(i,x,w,j,c,n) {
2438
+ while(--n >= 0) {
2439
+ var v = x*this[i++]+w[j]+c;
2440
+ c = Math.floor(v/0x4000000);
2441
+ w[j++] = v&0x3ffffff;
2442
+ }
2443
+ return c;
2444
+ }
2445
+ // am2 avoids a big mult-and-extract completely.
2446
+ // Max digit bits should be <= 30 because we do bitwise ops
2447
+ // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
2448
+ function am2(i,x,w,j,c,n) {
2449
+ var xl = x&0x7fff, xh = x>>15;
2450
+ while(--n >= 0) {
2451
+ var l = this[i]&0x7fff;
2452
+ var h = this[i++]>>15;
2453
+ var m = xh*l+h*xl;
2454
+ l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
2455
+ c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
2456
+ w[j++] = l&0x3fffffff;
2457
+ }
2458
+ return c;
2459
+ }
2460
+ // Alternately, set max digit bits to 28 since some
2461
+ // browsers slow down when dealing with 32-bit numbers.
2462
+ function am3(i,x,w,j,c,n) {
2463
+ var xl = x&0x3fff, xh = x>>14;
2464
+ while(--n >= 0) {
2465
+ var l = this[i]&0x3fff;
2466
+ var h = this[i++]>>14;
2467
+ var m = xh*l+h*xl;
2468
+ l = xl*l+((m&0x3fff)<<14)+w[j]+c;
2469
+ c = (l>>28)+(m>>14)+xh*h;
2470
+ w[j++] = l&0xfffffff;
2471
+ }
2472
+ return c;
2473
+ }
2474
+ if(j_lm && (typeof(navigator) !== 'undefined' && navigator.appName == "Microsoft Internet Explorer")) {
2475
+ BigInteger.prototype.am = am2;
2476
+ dbits = 30;
2477
+ }
2478
+ else if(j_lm && (typeof(navigator) !== 'undefined' && navigator.appName != "Netscape")) {
2479
+ BigInteger.prototype.am = am1;
2480
+ dbits = 26;
2481
+ }
2482
+ else { // Mozilla/Netscape seems to prefer am3
2483
+ BigInteger.prototype.am = am3;
2484
+ dbits = 28;
2485
+ }
2486
+
2487
+ BigInteger.prototype.DB = dbits;
2488
+ BigInteger.prototype.DM = ((1<<dbits)-1);
2489
+ BigInteger.prototype.DV = (1<<dbits);
2490
+
2491
+ var BI_FP = 52;
2492
+ BigInteger.prototype.FV = Math.pow(2,BI_FP);
2493
+ BigInteger.prototype.F1 = BI_FP-dbits;
2494
+ BigInteger.prototype.F2 = 2*dbits-BI_FP;
2495
+
2496
+ // Digit conversions
2497
+ var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
2498
+ var BI_RC = [];
2499
+ var rr,vv;
2500
+ rr = "0".charCodeAt(0);
2501
+ for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
2502
+ rr = "a".charCodeAt(0);
2503
+ for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
2504
+ rr = "A".charCodeAt(0);
2505
+ for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
2506
+
2507
+ function int2char(n) { return BI_RM.charAt(n); }
2508
+ function intAt(s,i) {
2509
+ var c = BI_RC[s.charCodeAt(i)];
2510
+ return (c==null)?-1:c;
2511
+ }
2512
+
2513
+ // (protected) copy this to r
2514
+ function bnpCopyTo(r) {
2515
+ for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
2516
+ r.t = this.t;
2517
+ r.s = this.s;
2518
+ }
2519
+
2520
+ // (protected) set from integer value x, -DV <= x < DV
2521
+ function bnpFromInt(x) {
2522
+ this.t = 1;
2523
+ this.s = (x<0)?-1:0;
2524
+ if(x > 0) this[0] = x;
2525
+ else if(x < -1) this[0] = x+DV;
2526
+ else this.t = 0;
2527
+ }
2528
+
2529
+ // return bigint initialized to value
2530
+ function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
2531
+
2532
+ // (protected) set from string and radix
2533
+ function bnpFromString(s,b) {
2534
+ var k;
2535
+ if(b == 16) k = 4;
2536
+ else if(b == 8) k = 3;
2537
+ else if(b == 256) k = 8; // byte array
2538
+ else if(b == 2) k = 1;
2539
+ else if(b == 32) k = 5;
2540
+ else if(b == 4) k = 2;
2541
+ else { this.fromRadix(s,b); return; }
2542
+ this.t = 0;
2543
+ this.s = 0;
2544
+ var i = s.length, mi = false, sh = 0;
2545
+ while(--i >= 0) {
2546
+ var x = (k==8)?s[i]&0xff:intAt(s,i);
2547
+ if(x < 0) {
2548
+ if(s.charAt(i) == "-") mi = true;
2549
+ continue;
2550
+ }
2551
+ mi = false;
2552
+ if(sh == 0)
2553
+ this[this.t++] = x;
2554
+ else if(sh+k > this.DB) {
2555
+ this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
2556
+ this[this.t++] = (x>>(this.DB-sh));
2557
+ }
2558
+ else
2559
+ this[this.t-1] |= x<<sh;
2560
+ sh += k;
2561
+ if(sh >= this.DB) sh -= this.DB;
2562
+ }
2563
+ if(k == 8 && (s[0]&0x80) != 0) {
2564
+ this.s = -1;
2565
+ if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
2566
+ }
2567
+ this.clamp();
2568
+ if(mi) BigInteger.ZERO.subTo(this,this);
2569
+ }
2570
+
2571
+ // (protected) clamp off excess high words
2572
+ function bnpClamp() {
2573
+ var c = this.s&this.DM;
2574
+ if (this.t > 0) {
2575
+ var i = this.t;
2576
+ while (this[i]) {
2577
+ delete this[i];
2578
+ i++;
2579
+ }
2580
+ }
2581
+ // if (this.t > 1 && this[this.t]) delete this[this.t];
2582
+ // this.t > 1?
2583
+ while(this.t > 0 && this[this.t-1] == c) {
2584
+ --this.t;
2585
+ delete this[this.t];
2586
+ }
2587
+ }
2588
+
2589
+ // (public) return string representation in given radix
2590
+ function bnToString(b) {
2591
+ if(this.s < 0) return "-"+this.negate().toString(b);
2592
+ var k;
2593
+ if(b == 16) k = 4;
2594
+ else if(b == 8) k = 3;
2595
+ else if(b == 2) k = 1;
2596
+ else if(b == 32) k = 5;
2597
+ else if(b == 4) k = 2;
2598
+ else return this.toRadix(b);
2599
+ var km = (1<<k)-1, d, m = false, r = [], i = this.t;
2600
+ var p = this.DB-(i*this.DB)%k;
2601
+ if(i-- > 0) {
2602
+ if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r.push(int2char(d)); }
2603
+ while(i >= 0) {
2604
+ if(p < k) {
2605
+ d = (this[i]&((1<<p)-1))<<(k-p);
2606
+ d |= this[--i]>>(p+=this.DB-k);
2607
+ }
2608
+ else {
2609
+ d = (this[i]>>(p-=k))&km;
2610
+ if(p <= 0) { p += this.DB; --i; }
2611
+ }
2612
+ if(d > 0) m = true;
2613
+ if(m) r.push(int2char(d));
2614
+ }
2615
+ }
2616
+ return m?r.join(""):"0";
2617
+ }
2618
+
2619
+ // (public) -this
2620
+ function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
2621
+
2622
+ // (public) |this|
2623
+ function bnAbs() { return (this.s<0)?this.negate():this; }
2624
+
2625
+ // (public) return + if this > a, - if this < a, 0 if equal
2626
+ function bnCompareTo(a) {
2627
+ var r = this.s-a.s;
2628
+ if(r != 0) return r;
2629
+ var i = this.t;
2630
+ if ( this.s < 0 ) {
2631
+ r = a.t - i;
2632
+ }
2633
+ else {
2634
+ r = i - a.t;
2635
+ }
2636
+ if(r != 0) return r;
2637
+ while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
2638
+ return 0;
2639
+ }
2640
+
2641
+ // returns bit length of the integer x
2642
+ function nbits(x) {
2643
+ var r = 1, t;
2644
+ if((t=x>>>16) != 0) { x = t; r += 16; }
2645
+ if((t=x>>8) != 0) { x = t; r += 8; }
2646
+ if((t=x>>4) != 0) { x = t; r += 4; }
2647
+ if((t=x>>2) != 0) { x = t; r += 2; }
2648
+ if((t=x>>1) != 0) { x = t; r += 1; }
2649
+ return r;
2650
+ }
2651
+
2652
+ // (public) return the number of bits in "this"
2653
+ function bnBitLength() {
2654
+ if(this.t <= 0) return 0;
2655
+ return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
2656
+ }
2657
+
2658
+ // (protected) r = this << n*DB
2659
+ function bnpDLShiftTo(n,r) {
2660
+ var i;
2661
+ for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
2662
+ for(i = n-1; i >= 0; --i) r[i] = 0;
2663
+ r.t = this.t+n;
2664
+ r.s = this.s;
2665
+ r.clamp();
2666
+ }
2667
+
2668
+ // (protected) r = this >> n*DB
2669
+ function bnpDRShiftTo(n,r) {
2670
+ for(var i = n; i < this.t; ++i) r[i-n] = this[i];
2671
+ r.t = Math.max(this.t-n,0);
2672
+ r.s = this.s;
2673
+ r.clamp();
2674
+ }
2675
+
2676
+ // (protected) r = this << n
2677
+ function bnpLShiftTo(n,r) {
2678
+ var bs = n%this.DB;
2679
+ var cbs = this.DB-bs;
2680
+ var bm = (1<<cbs)-1;
2681
+ var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
2682
+ for(i = this.t-1; i >= 0; --i) {
2683
+ r[i+ds+1] = (this[i]>>cbs)|c;
2684
+ c = (this[i]&bm)<<bs;
2685
+ }
2686
+ for(i = ds-1; i >= 0; --i) r[i] = 0;
2687
+ r[ds] = c;
2688
+ r.t = this.t+ds+1;
2689
+ r.s = this.s;
2690
+ r.clamp();
2691
+ }
2692
+
2693
+ // (protected) r = this >> n
2694
+ function bnpRShiftTo(n,r) {
2695
+ r.s = this.s;
2696
+ var ds = Math.floor(n/this.DB);
2697
+ if(ds >= this.t) { r.t = 0; return; }
2698
+ var bs = n%this.DB;
2699
+ var cbs = this.DB-bs;
2700
+ var bm = (1<<bs)-1;
2701
+ r[0] = this[ds]>>bs;
2702
+ for(var i = ds+1; i < this.t; ++i) {
2703
+ r[i-ds-1] |= (this[i]&bm)<<cbs;
2704
+ r[i-ds] = this[i]>>bs;
2705
+ }
2706
+ if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
2707
+ r.t = this.t-ds;
2708
+ r.clamp();
2709
+ }
2710
+
2711
+ // (protected) r = this - a
2712
+ function bnpSubTo(a,r) {
2713
+ var i = 0, c = 0, m = Math.min(a.t,this.t);
2714
+ while(i < m) {
2715
+ c += this[i]-a[i];
2716
+ r[i++] = c&this.DM;
2717
+ c >>= this.DB;
2718
+ }
2719
+ if(a.t < this.t) {
2720
+ c -= a.s;
2721
+ while(i < this.t) {
2722
+ c += this[i];
2723
+ r[i++] = c&this.DM;
2724
+ c >>= this.DB;
2725
+ }
2726
+ c += this.s;
2727
+ }
2728
+ else {
2729
+ c += this.s;
2730
+ while(i < a.t) {
2731
+ c -= a[i];
2732
+ r[i++] = c&this.DM;
2733
+ c >>= this.DB;
2734
+ }
2735
+ c -= a.s;
2736
+ }
2737
+ r.s = (c<0)?-1:0;
2738
+ if(c < -1) r[i++] = this.DV+c;
2739
+ else if(c > 0) r[i++] = c;
2740
+ r.t = i;
2741
+ r.clamp();
2742
+ }
2743
+
2744
+ // (protected) r = this * a, r != this,a (HAC 14.12)
2745
+ // "this" should be the larger one if appropriate.
2746
+ function bnpMultiplyTo(a,r) {
2747
+ var x = this.abs(), y = a.abs();
2748
+ var i = x.t;
2749
+ r.t = i+y.t;
2750
+ while(--i >= 0) r[i] = 0;
2751
+ for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
2752
+ r.s = 0;
2753
+ r.clamp();
2754
+ if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
2755
+ }
2756
+
2757
+ // (protected) r = this^2, r != this (HAC 14.16)
2758
+ function bnpSquareTo(r) {
2759
+ var x = this.abs();
2760
+ var i = r.t = 2*x.t;
2761
+ while(--i >= 0) r[i] = 0;
2762
+ for(i = 0; i < x.t-1; ++i) {
2763
+ var c = x.am(i,x[i],r,2*i,0,1);
2764
+ if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
2765
+ r[i+x.t] -= x.DV;
2766
+ r[i+x.t+1] = 1;
2767
+ }
2768
+ }
2769
+ if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
2770
+ r.s = 0;
2771
+ r.clamp();
2772
+ }
2773
+
2774
+ // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
2775
+ // r != q, this != m. q or r may be null.
2776
+ function bnpDivRemTo(m,q,r) {
2777
+ var pm = m.abs();
2778
+ if(pm.t <= 0) return;
2779
+ var pt = this.abs();
2780
+ if(pt.t < pm.t) {
2781
+ if(q != null) q.fromInt(0);
2782
+ if(r != null) this.copyTo(r);
2783
+ return;
2784
+ }
2785
+ if(r == null) r = nbi();
2786
+ var y = nbi(), ts = this.s, ms = m.s;
2787
+ var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
2788
+ if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
2789
+ else { pm.copyTo(y); pt.copyTo(r); }
2790
+ var ys = y.t;
2791
+ var y0 = y[ys-1];
2792
+ if(y0 == 0) return;
2793
+ var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
2794
+ var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
2795
+ var i = r.t, j = i-ys, t = (q==null)?nbi():q;
2796
+ y.dlShiftTo(j,t);
2797
+ if(r.compareTo(t) >= 0) {
2798
+ r[r.t++] = 1;
2799
+ r.subTo(t,r);
2800
+ }
2801
+ BigInteger.ONE.dlShiftTo(ys,t);
2802
+ t.subTo(y,y); // "negative" y so we can replace sub with am later
2803
+ while(y.t < ys) y[y.t++] = 0;
2804
+ while(--j >= 0) {
2805
+ // Estimate quotient digit
2806
+ var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
2807
+ if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
2808
+ y.dlShiftTo(j,t);
2809
+ r.subTo(t,r);
2810
+ while(r[i] < --qd) r.subTo(t,r);
2811
+ }
2812
+ }
2813
+ if(q != null) {
2814
+ r.drShiftTo(ys,q);
2815
+ if(ts != ms) BigInteger.ZERO.subTo(q,q);
2816
+ }
2817
+ r.t = ys;
2818
+ r.clamp();
2819
+ if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
2820
+ if(ts < 0) BigInteger.ZERO.subTo(r,r);
2821
+ }
2822
+
2823
+ // (public) this mod a
2824
+ function bnMod(a) {
2825
+ var r = nbi();
2826
+ this.abs().divRemTo(a,null,r);
2827
+ if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
2828
+ return r;
2829
+ }
2830
+
2831
+ // Modular reduction using "classic" algorithm
2832
+ function Classic(m) { this.m = m; }
2833
+ function cConvert(x) {
2834
+ if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
2835
+ else return x;
2836
+ }
2837
+ function cRevert(x) { return x; }
2838
+ function cReduce(x) { x.divRemTo(this.m,null,x); }
2839
+ function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
2840
+ function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
2841
+
2842
+ Classic.prototype.convert = cConvert;
2843
+ Classic.prototype.revert = cRevert;
2844
+ Classic.prototype.reduce = cReduce;
2845
+ Classic.prototype.mulTo = cMulTo;
2846
+ Classic.prototype.sqrTo = cSqrTo;
2847
+
2848
+ // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
2849
+ // justification:
2850
+ // xy == 1 (mod m)
2851
+ // xy = 1+km
2852
+ // xy(2-xy) = (1+km)(1-km)
2853
+ // x[y(2-xy)] = 1-k^2m^2
2854
+ // x[y(2-xy)] == 1 (mod m^2)
2855
+ // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
2856
+ // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
2857
+ // JS multiply "overflows" differently from C/C++, so care is needed here.
2858
+ function bnpInvDigit() {
2859
+ if(this.t < 1) return 0;
2860
+ var x = this[0];
2861
+ if((x&1) == 0) return 0;
2862
+ var y = x&3; // y == 1/x mod 2^2
2863
+ y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
2864
+ y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
2865
+ y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
2866
+ // last step - calculate inverse mod DV directly;
2867
+ // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
2868
+ y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
2869
+ // we really want the negative inverse, and -DV < y < DV
2870
+ return (y>0)?this.DV-y:-y;
2871
+ }
2872
+
2873
+ // Montgomery reduction
2874
+ function Montgomery(m) {
2875
+ this.m = m;
2876
+ this.mp = m.invDigit();
2877
+ this.mpl = this.mp&0x7fff;
2878
+ this.mph = this.mp>>15;
2879
+ this.um = (1<<(m.DB-15))-1;
2880
+ this.mt2 = 2*m.t;
2881
+ }
2882
+
2883
+ // xR mod m
2884
+ function montConvert(x) {
2885
+ var r = nbi();
2886
+ x.abs().dlShiftTo(this.m.t,r);
2887
+ r.divRemTo(this.m,null,r);
2888
+ if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
2889
+ return r;
2890
+ }
2891
+
2892
+ // x/R mod m
2893
+ function montRevert(x) {
2894
+ var r = nbi();
2895
+ x.copyTo(r);
2896
+ this.reduce(r);
2897
+ return r;
2898
+ }
2899
+
2900
+ // x = x/R mod m (HAC 14.32)
2901
+ function montReduce(x) {
2902
+ while(x.t <= this.mt2) // pad x so am has enough room later
2903
+ x[x.t++] = 0;
2904
+ for(var i = 0; i < this.m.t; ++i) {
2905
+ // faster way of calculating u0 = x[i]*mp mod DV
2906
+ var j = x[i]&0x7fff;
2907
+ var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
2908
+ // use am to combine the multiply-shift-add into one call
2909
+ j = i+this.m.t;
2910
+ x[j] += this.m.am(0,u0,x,i,0,this.m.t);
2911
+ // propagate carry
2912
+ while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
2913
+ }
2914
+ x.clamp();
2915
+ x.drShiftTo(this.m.t,x);
2916
+ if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
2917
+ }
2918
+
2919
+ // r = "x^2/R mod m"; x != r
2920
+ function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
2921
+
2922
+ // r = "xy/R mod m"; x,y != r
2923
+ function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
2924
+
2925
+ Montgomery.prototype.convert = montConvert;
2926
+ Montgomery.prototype.revert = montRevert;
2927
+ Montgomery.prototype.reduce = montReduce;
2928
+ Montgomery.prototype.mulTo = montMulTo;
2929
+ Montgomery.prototype.sqrTo = montSqrTo;
2930
+
2931
+ // (protected) true iff this is even
2932
+ function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
2933
+
2934
+ // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
2935
+ function bnpExp(e, z) {
2936
+ if (greaterThan(e, 0xffffffff)) {
2937
+ errbacks.throwDomainError('expt: exponent ' + e + ' too large');
2938
+ }
2939
+ if (lessThan(e, 1)) {
2940
+ return BigInteger.ONE;
2941
+ }
2942
+ var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
2943
+ g.copyTo(r);
2944
+ while(--i >= 0) {
2945
+ z.sqrTo(r,r2);
2946
+ if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
2947
+ else { var t = r; r = r2; r2 = t; }
2948
+ }
2949
+ return z.revert(r);
2950
+ }
2951
+
2952
+ // (public) this^e % m, 0 <= e < 2^32
2953
+ function bnModPowInt(e, m) {
2954
+ var z;
2955
+ if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
2956
+ return this.bnpExp(e, z);
2957
+ }
2958
+
2959
+ // protected
2960
+ BigInteger.prototype.copyTo = bnpCopyTo;
2961
+ BigInteger.prototype.fromInt = bnpFromInt;
2962
+ BigInteger.prototype.fromString = bnpFromString;
2963
+ BigInteger.prototype.clamp = bnpClamp;
2964
+ BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
2965
+ BigInteger.prototype.drShiftTo = bnpDRShiftTo;
2966
+ BigInteger.prototype.lShiftTo = bnpLShiftTo;
2967
+ BigInteger.prototype.rShiftTo = bnpRShiftTo;
2968
+ BigInteger.prototype.subTo = bnpSubTo;
2969
+ BigInteger.prototype.multiplyTo = bnpMultiplyTo;
2970
+ BigInteger.prototype.squareTo = bnpSquareTo;
2971
+ BigInteger.prototype.divRemTo = bnpDivRemTo;
2972
+ BigInteger.prototype.invDigit = bnpInvDigit;
2973
+ BigInteger.prototype.isEven = bnpIsEven;
2974
+ BigInteger.prototype.bnpExp = bnpExp; // renamed from exp, because we need the latter for Pyret
2975
+
2976
+ // public
2977
+ BigInteger.prototype.toString = bnToString;
2978
+ BigInteger.prototype.negate = bnNegate;
2979
+ BigInteger.prototype.abs = bnAbs;
2980
+ BigInteger.prototype.compareTo = bnCompareTo;
2981
+ BigInteger.prototype.bitLength = bnBitLength;
2982
+ BigInteger.prototype.mod = bnMod;
2983
+ BigInteger.prototype.modPowInt = bnModPowInt;
2984
+
2985
+ // "constants"
2986
+ BigInteger.ZERO = nbv(0);
2987
+ BigInteger.ONE = nbv(1);
2988
+
2989
+ // Copyright (c) 2005-2009 Tom Wu
2990
+ // All Rights Reserved.
2991
+ // See "LICENSE" for details.
2992
+
2993
+ // Extended JavaScript BN functions, required for RSA private ops.
2994
+
2995
+ // Version 1.1: new BigInteger("0", 10) returns "proper" zero
2996
+
2997
+ // (public)
2998
+ function bnClone() { var r = nbi(); this.copyTo(r); return r; }
2999
+
3000
+ // (public) return value as integer
3001
+ function bnIntValue() {
3002
+ if(this.s < 0) {
3003
+ if(this.t == 1) return this[0]-this.DV;
3004
+ else if(this.t == 0) return -1;
3005
+ }
3006
+ else if(this.t == 1) return this[0];
3007
+ else if(this.t == 0) return 0;
3008
+ // assumes 16 < DB < 32
3009
+ return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
3010
+ }
3011
+
3012
+ // (public) return value as byte
3013
+ function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
3014
+
3015
+ // (public) return value as short (assumes DB>=16)
3016
+ function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
3017
+
3018
+ // (protected) return x s.t. r^x < DV
3019
+ function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
3020
+
3021
+ // (public) 0 if this == 0, 1 if this > 0
3022
+ function bnSigNum() {
3023
+ if(this.s < 0) return -1;
3024
+ else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
3025
+ else return 1;
3026
+ }
3027
+
3028
+ // (protected) convert to radix string
3029
+ function bnpToRadix(b) {
3030
+ if(b == null) b = 10;
3031
+ if(this.signum() == 0 || b < 2 || b > 36) return "0";
3032
+ var cs = this.chunkSize(b);
3033
+ var a = Math.pow(b,cs);
3034
+ var d = nbv(a), y = nbi(), z = nbi(), r = "";
3035
+ this.divRemTo(d,y,z);
3036
+ while(y.signum() > 0) {
3037
+ r = (a+z.intValue()).toString(b).substr(1) + r;
3038
+ y.divRemTo(d,y,z);
3039
+ }
3040
+ return z.intValue().toString(b) + r;
3041
+ }
3042
+
3043
+ // (protected) convert from radix string
3044
+ function bnpFromRadix(s,b) {
3045
+ this.fromInt(0);
3046
+ if(b == null) b = 10;
3047
+ var cs = this.chunkSize(b);
3048
+ var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
3049
+ for(var i = 0; i < s.length; ++i) {
3050
+ var x = intAt(s,i);
3051
+ if(x < 0) {
3052
+ if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
3053
+ continue;
3054
+ }
3055
+ w = b*w+x;
3056
+ if(++j >= cs) {
3057
+ this.dMultiply(d);
3058
+ this.dAddOffset(w,0);
3059
+ j = 0;
3060
+ w = 0;
3061
+ }
3062
+ }
3063
+ if(j > 0) {
3064
+ this.dMultiply(Math.pow(b,j));
3065
+ this.dAddOffset(w,0);
3066
+ }
3067
+ if(mi) BigInteger.ZERO.subTo(this,this);
3068
+ }
3069
+
3070
+ // (protected) alternate constructor
3071
+ function bnpFromNumber(a,b,c) {
3072
+ if("number" == typeof b) {
3073
+ // new BigInteger(int,int,RNG)
3074
+ if(a < 2) this.fromInt(1);
3075
+ else {
3076
+ this.fromNumber(a,c);
3077
+ if(!this.testBit(a-1)) // force MSB set
3078
+ this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
3079
+ if(this.isEven()) this.dAddOffset(1,0); // force odd
3080
+ while(!this.isProbablePrime(b)) {
3081
+ this.dAddOffset(2,0);
3082
+ if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
3083
+ }
3084
+ }
3085
+ }
3086
+ else {
3087
+ // new BigInteger(int,RNG)
3088
+ var x = [], t = a&7;
3089
+ x.length = (a>>3)+1;
3090
+ b.nextBytes(x);
3091
+ if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
3092
+ this.fromString(x,256);
3093
+ }
3094
+ }
3095
+
3096
+ // (public) convert to bigendian byte array
3097
+ function bnToByteArray() {
3098
+ var i = this.t, r = [];
3099
+ r[0] = this.s;
3100
+ var p = this.DB-(i*this.DB)%8, d, k = 0;
3101
+ if(i-- > 0) {
3102
+ if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
3103
+ r[k++] = d|(this.s<<(this.DB-p));
3104
+ while(i >= 0) {
3105
+ if(p < 8) {
3106
+ d = (this[i]&((1<<p)-1))<<(8-p);
3107
+ d |= this[--i]>>(p+=this.DB-8);
3108
+ }
3109
+ else {
3110
+ d = (this[i]>>(p-=8))&0xff;
3111
+ if(p <= 0) { p += this.DB; --i; }
3112
+ }
3113
+ if((d&0x80) != 0) d |= -256;
3114
+ if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
3115
+ if(k > 0 || d != this.s) r[k++] = d;
3116
+ }
3117
+ }
3118
+ return r;
3119
+ }
3120
+
3121
+ function bnEquals(a) { return(this.compareTo(a)==0); }
3122
+ function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
3123
+ function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
3124
+
3125
+ // (protected) r = this op a (bitwise)
3126
+ function bnpBitwiseTo(a,op,r) {
3127
+ var i, f, m = Math.min(a.t,this.t);
3128
+ for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
3129
+ if(a.t < this.t) {
3130
+ f = a.s&this.DM;
3131
+ for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
3132
+ r.t = this.t;
3133
+ }
3134
+ else {
3135
+ f = this.s&this.DM;
3136
+ for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
3137
+ r.t = a.t;
3138
+ }
3139
+ r.s = op(this.s,a.s);
3140
+ r.clamp();
3141
+ }
3142
+
3143
+ // (public) this & a
3144
+ function op_and(x,y) { return x&y; }
3145
+ function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
3146
+
3147
+ // (public) this | a
3148
+ function op_or(x,y) { return x|y; }
3149
+ function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
3150
+
3151
+ // (public) this ^ a
3152
+ function op_xor(x,y) { return x^y; }
3153
+ function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
3154
+
3155
+ // (public) this & ~a
3156
+ function op_andnot(x,y) { return x&~y; }
3157
+ function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
3158
+
3159
+ // (public) ~this
3160
+ function bnNot() {
3161
+ var r = nbi();
3162
+ for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
3163
+ r.t = this.t;
3164
+ r.s = ~this.s;
3165
+ return r;
3166
+ }
3167
+
3168
+ // (public) this << n
3169
+ function bnShiftLeft(n) {
3170
+ var r = nbi();
3171
+ if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
3172
+ return r;
3173
+ }
3174
+
3175
+ // (public) this >> n
3176
+ function bnShiftRight(n) {
3177
+ var r = nbi();
3178
+ if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
3179
+ return r;
3180
+ }
3181
+
3182
+ // return index of lowest 1-bit in x, x < 2^31
3183
+ function lbit(x) {
3184
+ if(x == 0) return -1;
3185
+ var r = 0;
3186
+ if((x&0xffff) == 0) { x >>= 16; r += 16; }
3187
+ if((x&0xff) == 0) { x >>= 8; r += 8; }
3188
+ if((x&0xf) == 0) { x >>= 4; r += 4; }
3189
+ if((x&3) == 0) { x >>= 2; r += 2; }
3190
+ if((x&1) == 0) ++r;
3191
+ return r;
3192
+ }
3193
+
3194
+ // (public) returns index of lowest 1-bit (or -1 if none)
3195
+ function bnGetLowestSetBit() {
3196
+ for(var i = 0; i < this.t; ++i)
3197
+ if(this[i] != 0) return i*this.DB+lbit(this[i]);
3198
+ if(this.s < 0) return this.t*this.DB;
3199
+ return -1;
3200
+ }
3201
+
3202
+ // return number of 1 bits in x
3203
+ function cbit(x) {
3204
+ var r = 0;
3205
+ while(x != 0) { x &= x-1; ++r; }
3206
+ return r;
3207
+ }
3208
+
3209
+ // (public) return number of set bits
3210
+ function bnBitCount() {
3211
+ var r = 0, x = this.s&this.DM;
3212
+ for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
3213
+ return r;
3214
+ }
3215
+
3216
+ // (public) true iff nth bit is set
3217
+ function bnTestBit(n) {
3218
+ var j = Math.floor(n/this.DB);
3219
+ if(j >= this.t) return(this.s!=0);
3220
+ return((this[j]&(1<<(n%this.DB)))!=0);
3221
+ }
3222
+
3223
+ // (protected) this op (1<<n)
3224
+ function bnpChangeBit(n,op) {
3225
+ var r = BigInteger.ONE.shiftLeft(n);
3226
+ this.bitwiseTo(r,op,r);
3227
+ return r;
3228
+ }
3229
+
3230
+ // (public) this | (1<<n)
3231
+ function bnSetBit(n) { return this.changeBit(n,op_or); }
3232
+
3233
+ // (public) this & ~(1<<n)
3234
+ function bnClearBit(n) { return this.changeBit(n,op_andnot); }
3235
+
3236
+ // (public) this ^ (1<<n)
3237
+ function bnFlipBit(n) { return this.changeBit(n,op_xor); }
3238
+
3239
+ // (protected) r = this + a
3240
+ function bnpAddTo(a,r) {
3241
+ var i = 0, c = 0, m = Math.min(a.t,this.t);
3242
+ while(i < m) {
3243
+ c += this[i]+a[i];
3244
+ r[i++] = c&this.DM;
3245
+ c >>= this.DB;
3246
+ }
3247
+ if(a.t < this.t) {
3248
+ c += a.s;
3249
+ while(i < this.t) {
3250
+ c += this[i];
3251
+ r[i++] = c&this.DM;
3252
+ c >>= this.DB;
3253
+ }
3254
+ c += this.s;
3255
+ }
3256
+ else {
3257
+ c += this.s;
3258
+ while(i < a.t) {
3259
+ c += a[i];
3260
+ r[i++] = c&this.DM;
3261
+ c >>= this.DB;
3262
+ }
3263
+ c += a.s;
3264
+ }
3265
+ r.s = (c<0)?-1:0;
3266
+ if(c > 0) r[i++] = c;
3267
+ else if(c < -1) r[i++] = this.DV+c;
3268
+ r.t = i;
3269
+ r.clamp();
3270
+ }
3271
+
3272
+ // (public) this + a
3273
+ function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
3274
+
3275
+ // (public) this - a
3276
+ function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
3277
+
3278
+ // (public) this * a
3279
+ function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
3280
+
3281
+ // (public) this / a
3282
+ function bnDivide(a) {
3283
+ var r = nbi(); this.divRemTo(a,r,null);
3284
+ r.clamp();
3285
+ return r;
3286
+ }
3287
+
3288
+ // (public) this % a
3289
+ function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
3290
+
3291
+ // (public) [this/a,this%a]
3292
+ function bnDivideAndRemainder(a) {
3293
+ var q = nbi(), r = nbi();
3294
+ this.divRemTo(a,q,r);
3295
+ return [q,r];
3296
+ }
3297
+
3298
+ // (protected) this *= n, this >= 0, 1 < n < DV
3299
+ function bnpDMultiply(n) {
3300
+ this[this.t] = this.am(0,n-1,this,0,0,this.t);
3301
+ ++this.t;
3302
+ this.clamp();
3303
+ }
3304
+
3305
+ // (protected) this += n << w words, this >= 0
3306
+ function bnpDAddOffset(n,w) {
3307
+ if(n == 0) return;
3308
+ while(this.t <= w) this[this.t++] = 0;
3309
+ this[w] += n;
3310
+ while(this[w] >= this.DV) {
3311
+ this[w] -= this.DV;
3312
+ if(++w >= this.t) this[this.t++] = 0;
3313
+ ++this[w];
3314
+ }
3315
+ }
3316
+
3317
+ // A "null" reducer
3318
+ function NullExp() {}
3319
+ function nNop(x) { return x; }
3320
+ function nMulTo(x,y,r) { x.multiplyTo(y,r); }
3321
+ function nSqrTo(x,r) { x.squareTo(r); }
3322
+
3323
+ NullExp.prototype.convert = nNop;
3324
+ NullExp.prototype.revert = nNop;
3325
+ NullExp.prototype.mulTo = nMulTo;
3326
+ NullExp.prototype.sqrTo = nSqrTo;
3327
+
3328
+ // (public) this^e
3329
+ function bnPow(e) {
3330
+ return this.bnpExp(e,new NullExp());
3331
+ }
3332
+
3333
+ // (protected) r = lower n words of "this * a", a.t <= n
3334
+ // "this" should be the larger one if appropriate.
3335
+ function bnpMultiplyLowerTo(a,n,r) {
3336
+ var i = Math.min(this.t+a.t,n);
3337
+ r.s = 0; // assumes a,this >= 0
3338
+ r.t = i;
3339
+ while(i > 0) r[--i] = 0;
3340
+ var j;
3341
+ for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
3342
+ for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
3343
+ r.clamp();
3344
+ }
3345
+
3346
+ // (protected) r = "this * a" without lower n words, n > 0
3347
+ // "this" should be the larger one if appropriate.
3348
+ function bnpMultiplyUpperTo(a,n,r) {
3349
+ --n;
3350
+ var i = r.t = this.t+a.t-n;
3351
+ r.s = 0; // assumes a,this >= 0
3352
+ while(--i >= 0) r[i] = 0;
3353
+ for(i = Math.max(n-this.t,0); i < a.t; ++i)
3354
+ r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
3355
+ r.clamp();
3356
+ r.drShiftTo(1,r);
3357
+ }
3358
+
3359
+ // Barrett modular reduction
3360
+ function Barrett(m) {
3361
+ // setup Barrett
3362
+ this.r2 = nbi();
3363
+ this.q3 = nbi();
3364
+ BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
3365
+ this.mu = this.r2.divide(m);
3366
+ this.m = m;
3367
+ }
3368
+
3369
+ function barrettConvert(x) {
3370
+ if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
3371
+ else if(x.compareTo(this.m) < 0) return x;
3372
+ else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
3373
+ }
3374
+
3375
+ function barrettRevert(x) { return x; }
3376
+
3377
+ // x = x mod m (HAC 14.42)
3378
+ function barrettReduce(x) {
3379
+ x.drShiftTo(this.m.t-1,this.r2);
3380
+ if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
3381
+ this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
3382
+ this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
3383
+ while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
3384
+ x.subTo(this.r2,x);
3385
+ while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
3386
+ }
3387
+
3388
+ // r = x^2 mod m; x != r
3389
+ function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
3390
+
3391
+ // r = x*y mod m; x,y != r
3392
+ function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
3393
+
3394
+ Barrett.prototype.convert = barrettConvert;
3395
+ Barrett.prototype.revert = barrettRevert;
3396
+ Barrett.prototype.reduce = barrettReduce;
3397
+ Barrett.prototype.mulTo = barrettMulTo;
3398
+ Barrett.prototype.sqrTo = barrettSqrTo;
3399
+
3400
+ // (public) this^e % m (HAC 14.85)
3401
+ function bnModPow(e,m) {
3402
+ var i = e.bitLength(), k, r = nbv(1), z;
3403
+ if(i <= 0) return r;
3404
+ else if(i < 18) k = 1;
3405
+ else if(i < 48) k = 3;
3406
+ else if(i < 144) k = 4;
3407
+ else if(i < 768) k = 5;
3408
+ else k = 6;
3409
+ if(i < 8)
3410
+ z = new Classic(m);
3411
+ else if(m.isEven())
3412
+ z = new Barrett(m);
3413
+ else
3414
+ z = new Montgomery(m);
3415
+
3416
+ // precomputation
3417
+ var g = [], n = 3, k1 = k-1, km = (1<<k)-1;
3418
+ g[1] = z.convert(this);
3419
+ if(k > 1) {
3420
+ var g2 = nbi();
3421
+ z.sqrTo(g[1],g2);
3422
+ while(n <= km) {
3423
+ g[n] = nbi();
3424
+ z.mulTo(g2,g[n-2],g[n]);
3425
+ n += 2;
3426
+ }
3427
+ }
3428
+
3429
+ var j = e.t-1, w, is1 = true, r2 = nbi(), t;
3430
+ i = nbits(e[j])-1;
3431
+ while(j >= 0) {
3432
+ if(i >= k1) w = (e[j]>>(i-k1))&km;
3433
+ else {
3434
+ w = (e[j]&((1<<(i+1))-1))<<(k1-i);
3435
+ if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
3436
+ }
3437
+
3438
+ n = k;
3439
+ while((w&1) == 0) { w >>= 1; --n; }
3440
+ if((i -= n) < 0) { i += this.DB; --j; }
3441
+ if(is1) { // ret == 1, don't bother squaring or multiplying it
3442
+ g[w].copyTo(r);
3443
+ is1 = false;
3444
+ }
3445
+ else {
3446
+ while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
3447
+ if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
3448
+ z.mulTo(r2,g[w],r);
3449
+ }
3450
+
3451
+ while(j >= 0 && (e[j]&(1<<i)) == 0) {
3452
+ z.sqrTo(r,r2); t = r; r = r2; r2 = t;
3453
+ if(--i < 0) { i = this.DB-1; --j; }
3454
+ }
3455
+ }
3456
+ return z.revert(r);
3457
+ }
3458
+
3459
+ // (public) gcd(this,a) (HAC 14.54)
3460
+ function bnGCD(a) {
3461
+ var x = (this.s<0)?this.negate():this.clone();
3462
+ var y = (a.s<0)?a.negate():a.clone();
3463
+ if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
3464
+ var i = x.getLowestSetBit(), g = y.getLowestSetBit();
3465
+ if(g < 0) return x;
3466
+ if(i < g) g = i;
3467
+ if(g > 0) {
3468
+ x.rShiftTo(g,x);
3469
+ y.rShiftTo(g,y);
3470
+ }
3471
+ while(x.signum() > 0) {
3472
+ if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
3473
+ if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
3474
+ if(x.compareTo(y) >= 0) {
3475
+ x.subTo(y,x);
3476
+ x.rShiftTo(1,x);
3477
+ }
3478
+ else {
3479
+ y.subTo(x,y);
3480
+ y.rShiftTo(1,y);
3481
+ }
3482
+ }
3483
+ if(g > 0) y.lShiftTo(g,y);
3484
+ return y;
3485
+ }
3486
+
3487
+ // (protected) this % n, n < 2^26
3488
+ function bnpModInt(n) {
3489
+ if(n <= 0) return 0;
3490
+ var d = this.DV%n, r = (this.s<0)?n-1:0;
3491
+ if(this.t > 0)
3492
+ if(d == 0) r = this[0]%n;
3493
+ else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
3494
+ return r;
3495
+ }
3496
+
3497
+ // (public) 1/this % m (HAC 14.61)
3498
+ function bnModInverse(m) {
3499
+ var ac = m.isEven();
3500
+ if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
3501
+ var u = m.clone(), v = this.clone();
3502
+ var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
3503
+ while(u.signum() != 0) {
3504
+ while(u.isEven()) {
3505
+ u.rShiftTo(1,u);
3506
+ if(ac) {
3507
+ if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
3508
+ a.rShiftTo(1,a);
3509
+ }
3510
+ else if(!b.isEven()) b.subTo(m,b);
3511
+ b.rShiftTo(1,b);
3512
+ }
3513
+ while(v.isEven()) {
3514
+ v.rShiftTo(1,v);
3515
+ if(ac) {
3516
+ if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
3517
+ c.rShiftTo(1,c);
3518
+ }
3519
+ else if(!d.isEven()) d.subTo(m,d);
3520
+ d.rShiftTo(1,d);
3521
+ }
3522
+ if(u.compareTo(v) >= 0) {
3523
+ u.subTo(v,u);
3524
+ if(ac) a.subTo(c,a);
3525
+ b.subTo(d,b);
3526
+ }
3527
+ else {
3528
+ v.subTo(u,v);
3529
+ if(ac) c.subTo(a,c);
3530
+ d.subTo(b,d);
3531
+ }
3532
+ }
3533
+ if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
3534
+ if(d.compareTo(m) >= 0) return d.subtract(m);
3535
+ if(d.signum() < 0) d.addTo(m,d); else return d;
3536
+ if(d.signum() < 0) return d.add(m); else return d;
3537
+ }
3538
+
3539
+ var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
3540
+ var lplim = (1<<26)/lowprimes[lowprimes.length-1];
3541
+
3542
+ // (public) test primality with certainty >= 1-.5^t
3543
+ function bnIsProbablePrime(t) {
3544
+ var i, x = this.abs();
3545
+ if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
3546
+ for(i = 0; i < lowprimes.length; ++i)
3547
+ if(x[0] == lowprimes[i]) return true;
3548
+ return false;
3549
+ }
3550
+ if(x.isEven()) return false;
3551
+ i = 1;
3552
+ while(i < lowprimes.length) {
3553
+ var m = lowprimes[i], j = i+1;
3554
+ while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
3555
+ m = x.modInt(m);
3556
+ while(i < j) if(m%lowprimes[i++] == 0) return false;
3557
+ }
3558
+ return x.millerRabin(t);
3559
+ }
3560
+
3561
+ // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
3562
+ function bnpMillerRabin(t) {
3563
+ var n1 = this.subtract(BigInteger.ONE);
3564
+ var k = n1.getLowestSetBit();
3565
+ if(k <= 0) return false;
3566
+ var r = n1.shiftRight(k);
3567
+ t = (t+1)>>1;
3568
+ if(t > lowprimes.length) t = lowprimes.length;
3569
+ var a = nbi();
3570
+ for(var i = 0; i < t; ++i) {
3571
+ a.fromInt(lowprimes[i]);
3572
+ var y = a.modPow(r,this);
3573
+ if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
3574
+ var j = 1;
3575
+ while(j++ < k && y.compareTo(n1) != 0) {
3576
+ y = y.modPowInt(2,this);
3577
+ if(y.compareTo(BigInteger.ONE) == 0) return false;
3578
+ }
3579
+ if(y.compareTo(n1) != 0) return false;
3580
+ }
3581
+ }
3582
+ return true;
3583
+ }
3584
+
3585
+ // protected
3586
+ BigInteger.prototype.chunkSize = bnpChunkSize;
3587
+ BigInteger.prototype.toRadix = bnpToRadix;
3588
+ BigInteger.prototype.fromRadix = bnpFromRadix;
3589
+ BigInteger.prototype.fromNumber = bnpFromNumber;
3590
+ BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
3591
+ BigInteger.prototype.changeBit = bnpChangeBit;
3592
+ BigInteger.prototype.addTo = bnpAddTo;
3593
+ BigInteger.prototype.dMultiply = bnpDMultiply;
3594
+ BigInteger.prototype.dAddOffset = bnpDAddOffset;
3595
+ BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
3596
+ BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
3597
+ BigInteger.prototype.modInt = bnpModInt;
3598
+ BigInteger.prototype.millerRabin = bnpMillerRabin;
3599
+
3600
+ // public
3601
+ BigInteger.prototype.clone = bnClone;
3602
+ BigInteger.prototype.intValue = bnIntValue;
3603
+ BigInteger.prototype.byteValue = bnByteValue;
3604
+ BigInteger.prototype.shortValue = bnShortValue;
3605
+ BigInteger.prototype.signum = bnSigNum;
3606
+ BigInteger.prototype.toByteArray = bnToByteArray;
3607
+ BigInteger.prototype.equals = bnEquals;
3608
+ BigInteger.prototype.min = bnMin;
3609
+ BigInteger.prototype.max = bnMax;
3610
+ BigInteger.prototype.and = bnAnd;
3611
+ BigInteger.prototype.or = bnOr;
3612
+ BigInteger.prototype.xor = bnXor;
3613
+ BigInteger.prototype.andNot = bnAndNot;
3614
+ BigInteger.prototype.not = bnNot;
3615
+ BigInteger.prototype.shiftLeft = bnShiftLeft;
3616
+ BigInteger.prototype.shiftRight = bnShiftRight;
3617
+ BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
3618
+ BigInteger.prototype.bitCount = bnBitCount;
3619
+ BigInteger.prototype.testBit = bnTestBit;
3620
+ BigInteger.prototype.setBit = bnSetBit;
3621
+ BigInteger.prototype.clearBit = bnClearBit;
3622
+ BigInteger.prototype.flipBit = bnFlipBit;
3623
+ BigInteger.prototype.add = bnAdd;
3624
+ BigInteger.prototype.subtract = bnSubtract;
3625
+ BigInteger.prototype.multiply = bnMultiply;
3626
+ BigInteger.prototype.divide = bnDivide;
3627
+ BigInteger.prototype.remainder = bnRemainder;
3628
+ BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
3629
+ BigInteger.prototype.modPow = bnModPow;
3630
+ BigInteger.prototype.modInverse = bnModInverse;
3631
+ BigInteger.prototype.pow = bnPow;
3632
+ BigInteger.prototype.gcd = bnGCD;
3633
+ BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
3634
+
3635
+ // BigInteger interfaces not implemented in jsbn:
3636
+
3637
+ // BigInteger(int signum, byte[] magnitude)
3638
+ // double doubleValue()
3639
+ // float floatValue()
3640
+ // int hashCode()
3641
+ // long longValue()
3642
+ // static BigInteger valueOf(long val)
3643
+
3644
+ //////////////////////////////////////////////////////////////////////
3645
+ //////////////////////////////////////////////////////////////////////
3646
+ //////////////////////////////////////////////////////////////////////
3647
+ //////////////////////////////////////////////////////////////////////
3648
+ //////////////////////////////////////////////////////////////////////
3649
+ // END OF copy-and-paste of jsbn.
3650
+
3651
+ BigInteger.NEGATIVE_ONE = BigInteger.ONE.negate();
3652
+
3653
+ // Other methods we need to add for compatibilty with js-numbers numeric tower.
3654
+
3655
+ // add is implemented above.
3656
+ // subtract is implemented above.
3657
+ // multiply is implemented above.
3658
+ // equals is implemented above.
3659
+ // abs is implemented above.
3660
+ // negate is defined above.
3661
+
3662
+ // makeBignum: string -> BigInteger
3663
+ var makeBignum = function(s) {
3664
+ if (typeof(s) === 'number') { s = s + ''; }
3665
+ s = expandExponent(s);
3666
+ return new BigInteger(s, 10);
3667
+ };
3668
+
3669
+ var zerostring = function(n) {
3670
+ var buf = [];
3671
+ for (var i = 0; i < n; i++) {
3672
+ buf.push('0');
3673
+ }
3674
+ return buf.join('');
3675
+ };
3676
+
3677
+ BigInteger.prototype.isFinite = function() {
3678
+ return true;
3679
+ };
3680
+
3681
+ BigInteger.prototype.isInteger = function() {
3682
+ return true;
3683
+ };
3684
+
3685
+ BigInteger.prototype.isRational = function() {
3686
+ return true;
3687
+ };
3688
+
3689
+ BigInteger.prototype.isExact = BigInteger.prototype.isRational;
3690
+
3691
+ BigInteger.prototype.isReal = function() {
3692
+ return true;
3693
+ };
3694
+
3695
+ BigInteger.prototype.isRoughnum = function() {
3696
+ return false;
3697
+ };
3698
+
3699
+ BigInteger.prototype.isPositive = function() {
3700
+ return this.compareTo(BigInteger.ZERO) > 0;
3701
+ };
3702
+
3703
+ BigInteger.prototype.isNonNegative = function() {
3704
+ return this.compareTo(BigInteger.ZERO) >= 0;
3705
+ };
3706
+
3707
+ BigInteger.prototype.isNegative = function() {
3708
+ return this.compareTo(BigInteger.ZERO) < 0;
3709
+ };
3710
+
3711
+ BigInteger.prototype.isNonPositive = function() {
3712
+ return this.compareTo(BigInteger.ZERO) <= 0;
3713
+ };
3714
+
3715
+ BigInteger.prototype.toRational = function() {
3716
+ return this;
3717
+ };
3718
+
3719
+ BigInteger.prototype.toExact = BigInteger.prototype.toRational;
3720
+
3721
+ BigInteger.prototype.toFixnum = function() {
3722
+ var a = splitIntIntoMantissaExpt(this);
3723
+ //console.log('bigint.tofixnum of', this);
3724
+ //console.log('split = ', a);
3725
+ var r = Number(String(a[0]) + 'e' + String(a[1]));
3726
+ //console.log('returning', r);
3727
+ return r;
3728
+ }
3729
+
3730
+ BigInteger.prototype.toRoughnum = function() {
3731
+ return Roughnum.makeInstance(this.toFixnum());
3732
+ };
3733
+
3734
+ BigInteger.prototype.greaterThan = function(other) {
3735
+ return this.compareTo(other) > 0;
3736
+ };
3737
+
3738
+ BigInteger.prototype.greaterThanOrEqual = function(other) {
3739
+ return this.compareTo(other) >= 0;
3740
+ };
3741
+
3742
+ BigInteger.prototype.lessThan = function(other) {
3743
+ return this.compareTo(other) < 0;
3744
+ };
3745
+
3746
+ BigInteger.prototype.lessThanOrEqual = function(other) {
3747
+ return this.compareTo(other) <= 0;
3748
+ };
3749
+
3750
+ // divide: pyretnum -> pyretnum
3751
+ // WARNING NOTE: we override the old version of divide.
3752
+ BigInteger.prototype.divide = function(other) {
3753
+ var quotientAndRemainder = bnDivideAndRemainder.call(this, other);
3754
+ if (quotientAndRemainder[1].compareTo(BigInteger.ZERO) === 0) {
3755
+ return quotientAndRemainder[0];
3756
+ } else {
3757
+ var result = add(quotientAndRemainder[0],
3758
+ Rational.makeInstance(quotientAndRemainder[1], other));
3759
+ return result;
3760
+ }
3761
+ };
3762
+
3763
+ BigInteger.prototype.numerator = function() {
3764
+ return this;
3765
+ };
3766
+
3767
+ BigInteger.prototype.denominator = function() {
3768
+ return 1;
3769
+ };
3770
+
3771
+ (function() {
3772
+ // Classic implementation of Newton-Raphson square-root search,
3773
+ // adapted for integer-sqrt.
3774
+ // http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number
3775
+ var searchIter = function(n, guess) {
3776
+ while(!(lessThanOrEqual(sqr(guess),n) &&
3777
+ lessThan(n,sqr(add(guess, 1))))) {
3778
+ guess = floor(divide(add(guess,
3779
+ floor(divide(n, guess))),
3780
+ 2));
3781
+ }
3782
+ return guess;
3783
+ };
3784
+
3785
+ // integerSqrt: -> pyretnum
3786
+ BigInteger.prototype.integerSqrt = function() {
3787
+ var n;
3788
+ if(sign(this) >= 0) {
3789
+ return searchIter(this, this);
3790
+ } else {
3791
+ errbacks.throwDomainError('integerSqrt of negative bignum ' + this);
3792
+ }
3793
+ };
3794
+ })();
3795
+
3796
+ (function() {
3797
+ // Get an approximation using integerSqrt, and then start another
3798
+ // Newton-Raphson search if necessary.
3799
+ BigInteger.prototype.sqrt = function() {
3800
+ var approx = this.integerSqrt(), fix;
3801
+ if (eqv(sqr(approx), this)) {
3802
+ return approx;
3803
+ }
3804
+ fix = toFixnum(this);
3805
+ if (isFinite(fix)) {
3806
+ return Roughnum.makeInstance(Math.sqrt(fix));
3807
+ } else {
3808
+ return approx;
3809
+ }
3810
+ };
3811
+ })();
3812
+
3813
+ // sqrt: -> pyretnum
3814
+ // http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number
3815
+ // Produce the square root.
3816
+
3817
+ // floor: -> pyretnum
3818
+ // Produce the floor.
3819
+ BigInteger.prototype.floor = function() {
3820
+ return this;
3821
+ }
3822
+
3823
+ // ceiling: -> pyretnum
3824
+ // Produce the ceiling.
3825
+ BigInteger.prototype.ceiling = function() {
3826
+ return this;
3827
+ }
3828
+
3829
+ // round: -> pyretnum
3830
+ // Round to the nearest integer.
3831
+ BigInteger.prototype.round = function() {
3832
+ return this;
3833
+ };
3834
+
3835
+ BigInteger.prototype.roundEven = function() {
3836
+ return this;
3837
+ };
3838
+
3839
+ // log: -> pyretnum
3840
+ // Produce the log.
3841
+ BigInteger.prototype.log = function() {
3842
+ return log(this);
3843
+ };
3844
+
3845
+ // tan: -> pyretnum
3846
+ // Produce the tan.
3847
+ BigInteger.prototype.tan = function() {
3848
+ return tan(this.toFixnum());
3849
+ };
3850
+
3851
+ // atan: -> pyretnum
3852
+ // Produce the arc tangent.
3853
+ BigInteger.prototype.atan = function() {
3854
+ return atan(this.toFixnum());
3855
+ };
3856
+
3857
+ // cos: -> pyretnum
3858
+ // Produce the cosine.
3859
+ BigInteger.prototype.cos = function() {
3860
+ return cos(this.toFixnum());
3861
+ };
3862
+
3863
+ // sin: -> pyretnum
3864
+ // Produce the sine.
3865
+ BigInteger.prototype.sin = function() {
3866
+ return sin(this.toFixnum());
3867
+ };
3868
+
3869
+ // expt: pyretnum -> pyretnum
3870
+ // Produce the power to the input.
3871
+ BigInteger.prototype.expt = function(n) {
3872
+ return bnPow.call(this, n);
3873
+ };
3874
+
3875
+ // exp: -> pyretnum
3876
+ // Produce e raised to the given power.
3877
+ BigInteger.prototype.exp = function() {
3878
+ var res = Math.exp(this.toFixnum());
3879
+ if (!isFinite(res))
3880
+ errbacks.throwDomainError('exp: argument too large: ' + this);
3881
+ return Roughnum.makeInstance(res);
3882
+ };
3883
+
3884
+ // acos: -> pyretnum
3885
+ // Produce the arc cosine.
3886
+ BigInteger.prototype.acos = function() {
3887
+ return acos(this.toFixnum());
3888
+ };
3889
+
3890
+ // asin: -> pyretnum
3891
+ // Produce the arc sine.
3892
+ BigInteger.prototype.asin = function() {
3893
+ return asin(this.toFixnum());
3894
+ };
3895
+
3896
+ //////////////////////////////////////////////////////////////////////
3897
+ // getResidue: integer, integer, integer -> [string, string]
3898
+ //
3899
+ // Given the numerator and denominator of a proper (<= 1) fraction,
3900
+ // returns two strings constituting its repeating-decimal representation,
3901
+ // where the first string is the non-repeating digits immediately after the
3902
+ // decimal point, and the second string is the repeating digits thereafter.
3903
+ // The third argument is the limit on the size of the repeating digits.
3904
+ // If exceeded, the second string is `...`.
3905
+ var getResidue = function(r, d, limit) {
3906
+ var digits = [];
3907
+ var seenRemainders = {};
3908
+ seenRemainders[r] = true;
3909
+ while(true) {
3910
+ if (limit-- <= 0) {
3911
+ return [digits.join(''), '...']
3912
+ }
3913
+
3914
+ var nextDigit = quotient(
3915
+ multiply(r, 10), d);
3916
+ var nextRemainder = remainder(
3917
+ multiply(r, 10),
3918
+ d);
3919
+ digits.push(nextDigit.toString());
3920
+ if (seenRemainders[nextRemainder]) {
3921
+ r = nextRemainder;
3922
+ break;
3923
+ } else {
3924
+ seenRemainders[nextRemainder] = true;
3925
+ r = nextRemainder;
3926
+ }
3927
+ }
3928
+
3929
+ var firstRepeatingRemainder = r;
3930
+ var repeatingDigits = [];
3931
+ while (true) {
3932
+ var nextDigit = quotient(multiply(r, 10), d);
3933
+ var nextRemainder = remainder(
3934
+ multiply(r, 10),
3935
+ d);
3936
+ repeatingDigits.push(nextDigit.toString());
3937
+ if (equals(nextRemainder, firstRepeatingRemainder)) {
3938
+ break;
3939
+ } else {
3940
+ r = nextRemainder;
3941
+ }
3942
+ };
3943
+
3944
+ var digitString = digits.join('');
3945
+ var repeatingDigitString = repeatingDigits.join('');
3946
+
3947
+ while (digitString.length >= repeatingDigitString.length &&
3948
+ (digitString.substring(
3949
+ digitString.length - repeatingDigitString.length)
3950
+ === repeatingDigitString)) {
3951
+ digitString = digitString.substring(
3952
+ 0, digitString.length - repeatingDigitString.length);
3953
+ }
3954
+
3955
+ return [digitString, repeatingDigitString];
3956
+
3957
+ };
3958
+
3959
+ //////////////////////////////////////////////////////////////////////
3960
+ // toRepeatingDecimal: jsnum jsnum {limit: number}? -> [string, string, string]
3961
+ //
3962
+ // Given the numerator and denominator parts of a rational,
3963
+ // produces the repeating-decimal representation, where the first
3964
+ // part are the digits before the decimal, the second are the
3965
+ // non-repeating digits after the decimal, and the third are the
3966
+ // remaining repeating decimals.
3967
+ //
3968
+ // An optional limit on the decimal expansion can be provided via
3969
+ // a `limit` field of an object supplied as a third argument. This
3970
+ // cuts off the search if we go past the limit.
3971
+ // If this happens, the third string returned becomes '...' to indicate
3972
+ // that the search was prematurely cut off.
3973
+ // The default limit is 512.
3974
+ var toRepeatingDecimal = function(n, d, options) {
3975
+ // default limit on decimal expansion; can be overridden
3976
+ var limit = 512;
3977
+ if (options && typeof(options.limit) !== 'undefined') {
3978
+ limit = options.limit;
3979
+ }
3980
+ if (! isInteger(n)) {
3981
+ errbacks.throwDomainError('toRepeatingDecimal: n ' + n.toString() +
3982
+ " is not an integer.");
3983
+ }
3984
+ if (! isInteger(d)) {
3985
+ errbacks.throwDomainError('toRepeatingDecimal: d ' + d.toString() +
3986
+ " is not an integer.");
3987
+ }
3988
+ if (equals(d, 0)) {
3989
+ errbacks.throwDomainError('toRepeatingDecimal: d equals 0');
3990
+ }
3991
+ if (lessThan(d, 0)) {
3992
+ errbacks.throwDomainError('toRepeatingDecimal: d < 0');
3993
+ }
3994
+ var sign = (lessThan(n, 0) ? "-" : "");
3995
+ n = abs(n);
3996
+ var beforeDecimalPoint = sign + quotient(n, d);
3997
+ var afterDecimals = getResidue(remainder(n, d), d, limit);
3998
+ return [beforeDecimalPoint].concat(afterDecimals);
3999
+ };
4000
+ //////////////////////////////////////////////////////////////////////
4001
+ // toStringDigits: jsnum jsnum -> string
4002
+ // Converts the number to a string, providing digits precision in the
4003
+ // output. If digits is positive, provides that many digits to the right
4004
+ // of the decimal point (including adding zeroes beyond the actual precision of
4005
+ // the number). If digits is negative, rounds that many positions to the
4006
+ // left of the decimal, replacing them with zeroes.
4007
+ //
4008
+ // Note that num-to-string-digits is only for formatting, and its
4009
+ // output's apparent precision may be unrelated to the actual precision of the
4010
+ // input number, which may have been an approximation, or unrepresentable in
4011
+ // decimal.
4012
+ function toStringDigits(n, digits) {
4013
+ if (!isInteger(digits)) {
4014
+ errbacks.throwDomainError('num-to-string-digits: digits should be an integer');
4015
+ }
4016
+ var tenDigits = expt(10, digits);
4017
+ var d = toFixnum(digits);
4018
+ n = divide(round(multiply(n, tenDigits)), tenDigits);
4019
+ if (isInteger(n)) {
4020
+ var ans = n.toString();
4021
+ if (d >= 1) {
4022
+ ans += '.';
4023
+ for (var i = 0; i < d; i++) {
4024
+ ans += '0';
4025
+ }
4026
+ }
4027
+ return ans;
4028
+ }
4029
+ // n is not an integer implies that d >= 1
4030
+ var decimal = toRepeatingDecimal(n.numerator(), n.denominator(), undefined);
4031
+ var ans = decimal[1].toString();
4032
+ while (ans.length < d) {
4033
+ ans += decimal[2];
4034
+ }
4035
+ return decimal[0] + '.' + ans.substring(0, d);
4036
+ }
4037
+ //////////////////////////////////////////////////////////////////////
4038
+
4039
+ // External interface of js-numbers:
4040
+
4041
+ Numbers['fromFixnum'] = fromFixnum;
4042
+ Numbers['fromString'] = fromString;
4043
+ Numbers['fromSchemeString'] = fromSchemeString;
4044
+ Numbers['makeBignum'] = makeBignum;
4045
+ Numbers['makeRational'] = Rational.makeInstance;
4046
+ Numbers['makeRoughnum'] = Roughnum.makeInstance;
4047
+
4048
+ Numbers['isPyretNumber'] = isPyretNumber;
4049
+ Numbers['isRational'] = isRational;
4050
+ Numbers['isReal'] = isReal;
4051
+ Numbers['isExact'] = isExact;
4052
+ Numbers['isInteger'] = isInteger;
4053
+ Numbers['isRoughnum'] = isRoughnum;
4054
+ Numbers['isPositive'] = isPositive;
4055
+ Numbers['isNegative'] = isNegative;
4056
+ Numbers['isNonPositive'] = isNonPositive;
4057
+ Numbers['isNonNegative'] = isNonNegative;
4058
+
4059
+ Numbers['toFixnum'] = toFixnum;
4060
+ Numbers['toExact'] = toExact;
4061
+ Numbers['toRational'] = toRational;
4062
+ Numbers['toRoughnum'] = toRoughnum;
4063
+
4064
+ Numbers['add'] = add;
4065
+ Numbers['subtract'] = subtract;
4066
+ Numbers['multiply'] = multiply;
4067
+ Numbers['divide'] = divide;
4068
+ Numbers['equals'] = equals;
4069
+ Numbers['equalsAnyZero'] = equalsAnyZero;
4070
+ Numbers['eqv'] = eqv; // why is this being exported?
4071
+ Numbers['roughlyEquals'] = roughlyEquals;
4072
+ Numbers['roughlyEqualsRel'] = roughlyEqualsRel;
4073
+ Numbers['greaterThanOrEqual'] = greaterThanOrEqual;
4074
+ Numbers['lessThanOrEqual'] = lessThanOrEqual;
4075
+ Numbers['greaterThan'] = greaterThan;
4076
+ Numbers['lessThan'] = lessThan;
4077
+ Numbers['expt'] = expt;
4078
+ Numbers['exp'] = exp;
4079
+ Numbers['modulo'] = modulo;
4080
+ Numbers['numerator'] = numerator;
4081
+ Numbers['denominator'] = denominator;
4082
+ Numbers['integerSqrt'] = integerSqrt;
4083
+ Numbers['sqrt'] = sqrt;
4084
+ Numbers['abs'] = abs;
4085
+ Numbers['quotient'] = quotient;
4086
+ Numbers['remainder'] = remainder;
4087
+ Numbers['floor'] = floor;
4088
+ Numbers['ceiling'] = ceiling;
4089
+ Numbers['round'] = round;
4090
+ Numbers['roundEven'] = roundEven;
4091
+ Numbers['log'] = log;
4092
+ Numbers['tan'] = tan;
4093
+ Numbers['atan'] = atan;
4094
+ Numbers['atan2'] = atan2;
4095
+ Numbers['cos'] = cos;
4096
+ Numbers['sin'] = sin;
4097
+ Numbers['tan'] = tan;
4098
+ Numbers['acos'] = acos;
4099
+ Numbers['asin'] = asin;
4100
+ Numbers['sqr'] = sqr;
4101
+ Numbers['gcd'] = gcd;
4102
+ Numbers['lcm'] = lcm;
4103
+
4104
+ Numbers['toRepeatingDecimal'] = toRepeatingDecimal;
4105
+ Numbers['toStringDigits'] = toStringDigits;
4106
+
4107
+ // The following exposes the class representations for easier
4108
+ // integration with other projects.
4109
+ Numbers['BigInteger'] = BigInteger;
4110
+ Numbers['Rational'] = Rational;
4111
+ Numbers['Roughnum'] = Roughnum;
4112
+ Numbers['FloatPoint'] = Roughnum; //FIXME
4113
+ Numbers['Complex'] = Roughnum; //FIXME
4114
+
4115
+ Numbers['MIN_FIXNUM'] = MIN_FIXNUM;
4116
+ Numbers['MAX_FIXNUM'] = MAX_FIXNUM;
4117
+
4118
+ // the following exposes innards for testing
4119
+ Numbers['_innards'] = {
4120
+ NullExp: NullExp,
4121
+ _integerIsZero: _integerIsZero,
4122
+ _integerIsOne: _integerIsOne,
4123
+ _integerIsNegativeOne: _integerIsNegativeOne,
4124
+ _integerModulo: _integerModulo,
4125
+ _integerGcd: _integerGcd,
4126
+ _integerDivideToFixnum: _integerDivideToFixnum,
4127
+ _integerEquals: _integerEquals,
4128
+ _integerGreaterThan: _integerGreaterThan,
4129
+ _integerLessThan: _integerLessThan,
4130
+ _integerGreaterThanOrEqual: _integerGreaterThanOrEqual,
4131
+ _integerLessThanOrEqual: _integerLessThanOrEqual,
4132
+ splitIntIntoMantissaExpt: splitIntIntoMantissaExpt,
4133
+ getResidue: getResidue,
4134
+ nbi: nbi,
4135
+ integerNthRoot: integerNthRoot,
4136
+ liftFixnumInteger: liftFixnumInteger,
4137
+ makeIntegerUnOp: makeIntegerUnOp,
4138
+ makeIntegerBinop: makeIntegerBinop,
4139
+ makeNumericBinop: makeNumericBinop,
4140
+ nthRoot: nthRoot,
4141
+ sign: sign,
4142
+ zfill: zfill,
4143
+ getErrbacks: function() { return errbacks; },
4144
+ setErrbacks: function(newErrbacks) {
4145
+ errbacks = newErrbacks;
4146
+ }
4147
+ };
4148
+
4149
+ return Numbers;
4150
+ }
4151
+
4152
+ var INITIAL_ERRBACKS = (function() {
4153
+ function makeThrower(tag) {
4154
+ return function(msg, ...extras) {
4155
+ var suffix = extras.length
4156
+ ? ' [' + extras.map(function(x) {
4157
+ try { return String(x); } catch (_) { return '<unprintable>'; }
4158
+ }).join(', ') + ']'
4159
+ : '';
4160
+ throw new Error('js-numbers ' + tag + ': ' + msg + suffix);
4161
+ };
4162
+ }
4163
+ return {
4164
+ throwDivByZero: makeThrower('division-by-zero'),
4165
+ throwDomainError: makeThrower('domain-error'),
4166
+ throwGeneralError: makeThrower('general-error'),
4167
+ throwIncomparableValues:makeThrower('incomparable-values'),
4168
+ throwInternalError: makeThrower('internal-error'),
4169
+ throwLogNonPositive: makeThrower('log-non-positive'),
4170
+ throwRelToleranceError: makeThrower('relative-tolerance-error'),
4171
+ throwSqrtNegative: makeThrower('sqrt-negative'),
4172
+ throwToleranceError: makeThrower('tolerance-error'),
4173
+ throwUndefinedValue: makeThrower('undefined-value'),
4174
+ };
4175
+ })();
4176
+
4177
+ // A single library instance. We can't regenerate this per call — the
4178
+ // class identities (Rational/Roughnum/BigInteger) have to be stable
4179
+ // across the module's lifetime or instanceof checks start failing.
4180
+ var DEFAULT_LIBRARY = MakeNumberLibrary(INITIAL_ERRBACKS);
4181
+ var getErrbacks = DEFAULT_LIBRARY._innards.getErrbacks;
4182
+ var setErrbacks = DEFAULT_LIBRARY._innards.setErrbacks;
4183
+
4184
+ // Parameterize-style wrappers: for one call, swap the library's current
4185
+ // errbacks in for whatever the caller supplied (or INITIAL_ERRBACKS if they
4186
+ // didn't), then restore on exit — including on throw via finally.
4187
+
4188
+ function wrapErrbacks1(f) {
4189
+ return function(a, errbacks) {
4190
+ var saved = getErrbacks();
4191
+ try {
4192
+ setErrbacks(errbacks ?? INITIAL_ERRBACKS);
4193
+ return f(a);
4194
+ } finally {
4195
+ setErrbacks(saved);
4196
+ }
4197
+ };
4198
+ }
4199
+
4200
+ function wrapErrbacks2(f) {
4201
+ return function(a, b, errbacks) {
4202
+ var saved = getErrbacks();
4203
+ try {
4204
+ setErrbacks(errbacks ?? INITIAL_ERRBACKS);
4205
+ return f(a, b);
4206
+ } finally {
4207
+ setErrbacks(saved);
4208
+ }
4209
+ };
4210
+ }
4211
+
4212
+ function wrapErrbacks3(f) {
4213
+ return function(a, b, c, errbacks) {
4214
+ var saved = getErrbacks();
4215
+ try {
4216
+ setErrbacks(errbacks ?? INITIAL_ERRBACKS);
4217
+ return f(a, b, c);
4218
+ } finally {
4219
+ setErrbacks(saved);
4220
+ }
4221
+ };
4222
+ }
4223
+
4224
+ // For exports with no fixed arity. A trailing errbacks argument is detected
4225
+ // by duck-typing on one of the throw* methods — pyretnums don't carry those,
4226
+ // so the ambiguity is only theoretical.
4227
+ function wrapErrbacksVariadic(f) {
4228
+ return function(...args) {
4229
+ var errbacks;
4230
+ var last = args.length > 0 ? args[args.length - 1] : undefined;
4231
+ if (last !== null && typeof last === 'object' &&
4232
+ typeof last.throwDomainError === 'function') {
4233
+ errbacks = args.pop();
4234
+ }
4235
+ var saved = getErrbacks();
4236
+ try {
4237
+ setErrbacks(errbacks ?? INITIAL_ERRBACKS);
4238
+ return f.apply(null, args);
4239
+ } finally {
4240
+ setErrbacks(saved);
4241
+ }
4242
+ };
4243
+ }
4244
+
4245
+ return {
4246
+ MakeNumberLibrary,
4247
+
4248
+ fromFixnum: wrapErrbacks1(DEFAULT_LIBRARY.fromFixnum),
4249
+ fromString: wrapErrbacks1(DEFAULT_LIBRARY.fromString),
4250
+ fromSchemeString: wrapErrbacks2(DEFAULT_LIBRARY.fromSchemeString),
4251
+ makeBignum: wrapErrbacks1(DEFAULT_LIBRARY.makeBignum),
4252
+
4253
+ isPyretNumber: wrapErrbacks1(DEFAULT_LIBRARY.isPyretNumber),
4254
+ isRational: wrapErrbacks1(DEFAULT_LIBRARY.isRational),
4255
+ isReal: wrapErrbacks1(DEFAULT_LIBRARY.isReal),
4256
+ isExact: wrapErrbacks1(DEFAULT_LIBRARY.isExact),
4257
+ isInteger: wrapErrbacks1(DEFAULT_LIBRARY.isInteger),
4258
+ isRoughnum: wrapErrbacks1(DEFAULT_LIBRARY.isRoughnum),
4259
+ isPositive: wrapErrbacks1(DEFAULT_LIBRARY.isPositive),
4260
+ isNegative: wrapErrbacks1(DEFAULT_LIBRARY.isNegative),
4261
+ isNonPositive: wrapErrbacks1(DEFAULT_LIBRARY.isNonPositive),
4262
+ isNonNegative: wrapErrbacks1(DEFAULT_LIBRARY.isNonNegative),
4263
+
4264
+ toFixnum: wrapErrbacks1(DEFAULT_LIBRARY.toFixnum),
4265
+ toExact: wrapErrbacks1(DEFAULT_LIBRARY.toExact),
4266
+ toRational: wrapErrbacks1(DEFAULT_LIBRARY.toRational),
4267
+ toRoughnum: wrapErrbacks1(DEFAULT_LIBRARY.toRoughnum),
4268
+
4269
+ add: wrapErrbacks2(DEFAULT_LIBRARY.add),
4270
+ subtract: wrapErrbacks2(DEFAULT_LIBRARY.subtract),
4271
+ multiply: wrapErrbacks2(DEFAULT_LIBRARY.multiply),
4272
+ divide: wrapErrbacks2(DEFAULT_LIBRARY.divide),
4273
+ equals: wrapErrbacks2(DEFAULT_LIBRARY.equals),
4274
+ equalsAnyZero: wrapErrbacks1(DEFAULT_LIBRARY.equalsAnyZero),
4275
+ eqv: wrapErrbacks2(DEFAULT_LIBRARY.eqv),
4276
+ roughlyEquals: wrapErrbacks3(DEFAULT_LIBRARY.roughlyEquals),
4277
+ roughlyEqualsRel: wrapErrbacksVariadic(DEFAULT_LIBRARY.roughlyEqualsRel),
4278
+ greaterThanOrEqual: wrapErrbacks2(DEFAULT_LIBRARY.greaterThanOrEqual),
4279
+ lessThanOrEqual: wrapErrbacks2(DEFAULT_LIBRARY.lessThanOrEqual),
4280
+ greaterThan: wrapErrbacks2(DEFAULT_LIBRARY.greaterThan),
4281
+ lessThan: wrapErrbacks2(DEFAULT_LIBRARY.lessThan),
4282
+ expt: wrapErrbacks2(DEFAULT_LIBRARY.expt),
4283
+ exp: wrapErrbacks1(DEFAULT_LIBRARY.exp),
4284
+ modulo: wrapErrbacks2(DEFAULT_LIBRARY.modulo),
4285
+ numerator: wrapErrbacks1(DEFAULT_LIBRARY.numerator),
4286
+ denominator: wrapErrbacks1(DEFAULT_LIBRARY.denominator),
4287
+ integerSqrt: wrapErrbacks1(DEFAULT_LIBRARY.integerSqrt),
4288
+ sqrt: wrapErrbacks1(DEFAULT_LIBRARY.sqrt),
4289
+ abs: wrapErrbacks1(DEFAULT_LIBRARY.abs),
4290
+ quotient: wrapErrbacks2(DEFAULT_LIBRARY.quotient),
4291
+ remainder: wrapErrbacks2(DEFAULT_LIBRARY.remainder),
4292
+ floor: wrapErrbacks1(DEFAULT_LIBRARY.floor),
4293
+ ceiling: wrapErrbacks1(DEFAULT_LIBRARY.ceiling),
4294
+ round: wrapErrbacks1(DEFAULT_LIBRARY.round),
4295
+ roundEven: wrapErrbacks1(DEFAULT_LIBRARY.roundEven),
4296
+ log: wrapErrbacks1(DEFAULT_LIBRARY.log),
4297
+ tan: wrapErrbacks1(DEFAULT_LIBRARY.tan),
4298
+ atan: wrapErrbacks1(DEFAULT_LIBRARY.atan),
4299
+ atan2: wrapErrbacks2(DEFAULT_LIBRARY.atan2),
4300
+ cos: wrapErrbacks1(DEFAULT_LIBRARY.cos),
4301
+ sin: wrapErrbacks1(DEFAULT_LIBRARY.sin),
4302
+ acos: wrapErrbacks1(DEFAULT_LIBRARY.acos),
4303
+ asin: wrapErrbacks1(DEFAULT_LIBRARY.asin),
4304
+ sqr: wrapErrbacks1(DEFAULT_LIBRARY.sqr),
4305
+ gcd: wrapErrbacks2(DEFAULT_LIBRARY.gcd),
4306
+ lcm: wrapErrbacks2(DEFAULT_LIBRARY.lcm),
4307
+
4308
+ toRepeatingDecimal: wrapErrbacks3(DEFAULT_LIBRARY.toRepeatingDecimal),
4309
+ toStringDigits: wrapErrbacks2(DEFAULT_LIBRARY.toStringDigits),
4310
+ }
4311
+ });