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.
- package/package.json +5 -2
- package/pyret-lang/lib/jglr/cyclicJSON.js +174 -0
- package/pyret-lang/lib/jglr/jglr.js +341 -0
- package/pyret-lang/lib/jglr/rnglr.js +2687 -0
- package/pyret-lang/src/js/base/js-numbers.js +4311 -0
- package/pyret-lang/src/js/base/pyret-tokenizer.js +579 -0
- package/pyret-lang/src/js/base/type-util.js +553 -0
|
@@ -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
|
+
});
|