@fable-org/fable-library-js 2.9.0 → 2.11.0

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/lib/big.js CHANGED
@@ -67,7 +67,6 @@ function _Big_() {
67
67
  x.s = n.s;
68
68
  x.e = n.e;
69
69
  x.c = n.c.slice();
70
- normalize(x);
71
70
  }
72
71
  else {
73
72
  if (typeof n !== 'string') {
@@ -91,14 +90,6 @@ function _Big_() {
91
90
  Big.strict = STRICT;
92
91
  return Big;
93
92
  }
94
- function normalize(x) {
95
- // x = round(x, DP, 0);
96
- if (x.c.length > 1 && !x.c[0]) {
97
- let i = x.c.findIndex(x => x);
98
- x.c = x.c.slice(i);
99
- x.e = x.e - i;
100
- }
101
- }
102
93
  /*
103
94
  * Parse the number or string value passed to a Big constructor.
104
95
  *
@@ -128,15 +119,13 @@ function parse(x, n) {
128
119
  e = n.length;
129
120
  }
130
121
  nl = n.length;
131
- // Determine leading zeros before decimal point.
132
- for (i = 0; i < e && i < nl && n.charAt(i) == '0';)
122
+ // Determine leading zeros.
123
+ for (i = 0; i < nl && n.charAt(i) == '0';)
133
124
  ++i;
134
- // original version (ignores decimal point).
135
- // // Determine leading zeros.
136
- // for (i = 0; i < nl && n.charAt(i) == '0';) ++i;
137
125
  if (i == nl) {
138
- // Zero.
139
- x.c = [x.e = 0];
126
+ // Zero, keeping the scale: 0.00 is c = [0], e = -2.
127
+ x.c = [0];
128
+ x.e = nl > e ? e - nl : 0;
140
129
  }
141
130
  else {
142
131
  x.e = e - i - 1;
@@ -150,8 +139,7 @@ function parse(x, n) {
150
139
  // // Convert string to array of digits without leading/trailing zeros.
151
140
  // for (e = 0; i <= nl;) x.c[e++] = +n.charAt(i++);
152
141
  }
153
- x = round(x, Big.DP + 1, Big.RM);
154
- return x;
142
+ return fit(x);
155
143
  }
156
144
  /*
157
145
  * Round Big x to a maximum of sd significant digits using rounding mode rm.
@@ -171,17 +159,11 @@ function round(x, sd, rm, more) {
171
159
  if (sd < 1) {
172
160
  more =
173
161
  rm === 3 && (more || !!xc[0]) || sd === 0 && (rm === 1 && xc[0] >= 5 ||
174
- rm === 2 && (xc[0] > 5 || xc[0] === 5 && (more || xc[1] !== UNDEFINED)));
162
+ rm === 2 && (xc[0] > 5 || xc[0] === 5 && (more || xc.some((d, i) => i > 0 && d))));
175
163
  xc.length = 1;
176
- if (more) {
177
- // 1, 0.1, 0.01, 0.001, 0.0001 etc.
178
- x.e = x.e - sd + 1;
179
- xc[0] = 1;
180
- }
181
- else {
182
- // Zero.
183
- xc[0] = x.e = 0;
184
- }
164
+ // 1, 0.1, 0.01, 0.001, 0.0001 etc., or zero at the same place.
165
+ x.e = x.e - sd + 1;
166
+ xc[0] = more ? 1 : 0;
185
167
  }
186
168
  else if (sd < xc.length) {
187
169
  // xc[sd] is the digit after the digit that may be rounded up.
@@ -189,7 +171,7 @@ function round(x, sd, rm, more) {
189
171
  more =
190
172
  rm === 1 && xc[sd] >= 5 ||
191
173
  rm === 2 && (xc[sd] > 5 || xc[sd] === 5 &&
192
- (more || xc[sd + 1] !== UNDEFINED || xc[sd - 1] & 1)) ||
174
+ (more || xc.some((d, i) => i > sd && d) || xc[sd - 1] & 1)) ||
193
175
  rm === 3 && (more || !isZero);
194
176
  // Remove any digits after the required precision.
195
177
  xc.length = sd--;
@@ -204,14 +186,59 @@ function round(x, sd, rm, more) {
204
186
  }
205
187
  }
206
188
  }
207
- // Remove trailing zeros.
208
- for (sd = xc.length; !xc[--sd];)
209
- xc.pop();
210
189
  }
211
190
  return x;
212
191
  }
213
- function hasNonzeroDigit(x) {
214
- return x.c.some(d => d !== 0);
192
+ // Largest System.Decimal mantissa, 2^96 - 1.
193
+ var MAX_MANTISSA = '79228162514264337593543950335'.split('').map(Number), OVERFLOW = 'Value was either too large or too small for a Decimal.';
194
+ /*
195
+ * Return the number of decimal places of Big x.
196
+ */
197
+ function scaleOf(x) {
198
+ return x.c.length - x.e - 1;
199
+ }
200
+ /*
201
+ * Pad Big x with trailing zeros up to dp decimal places.
202
+ */
203
+ function padScale(x, dp) {
204
+ if (!x.c[0]) {
205
+ x.e = Math.min(x.e, -dp);
206
+ }
207
+ else {
208
+ for (; scaleOf(x) < dp;)
209
+ x.c.push(0);
210
+ }
211
+ return x;
212
+ }
213
+ /*
214
+ * Return true if the digits c, padded with zeros to the length of MAX_MANTISSA, exceed it.
215
+ */
216
+ function exceedsMax(c) {
217
+ for (var i = 0; i < MAX_MANTISSA.length; i++) {
218
+ var d = i < c.length ? c[i] : 0;
219
+ if (d !== MAX_MANTISSA[i])
220
+ return d > MAX_MANTISSA[i];
221
+ }
222
+ return false;
223
+ }
224
+ /*
225
+ * Round Big x half to even so that it fits a System.Decimal: at most Big.DP decimal places
226
+ * and a mantissa no larger than MAX_MANTISSA. Throws when no decimal place is left to drop.
227
+ */
228
+ function fit(x) {
229
+ var scale = scaleOf(x), dp = Math.min(scale, Big.DP, Big.DP - x.e);
230
+ if (x.e > Big.DP)
231
+ throw Error(OVERFLOW);
232
+ if (dp < scale)
233
+ round(x, x.e + 1 + dp, 2);
234
+ if (x.e > Big.DP)
235
+ throw Error(OVERFLOW);
236
+ // Both the value and the mantissa itself must not exceed MAX_MANTISSA.
237
+ if (x.e === Big.DP && exceedsMax(x.c))
238
+ throw Error(OVERFLOW);
239
+ if (x.c.length === MAX_MANTISSA.length && exceedsMax(x.c))
240
+ round(x, x.c.length - 1, 2);
241
+ return x;
215
242
  }
216
243
  /*
217
244
  * Return a string representing the value of Big x in normal or exponential notation.
@@ -221,6 +248,8 @@ function stringify(x, doExponential, isNonzero) {
221
248
  var e = x.e, s = x.c.join(''), n = s.length;
222
249
  // Exponential notation?
223
250
  if (doExponential) {
251
+ if (!x.c[0])
252
+ e = 0;
224
253
  s = s.charAt(0) + (n > 1 ? '.' + s.slice(1) : '') + (e < 0 ? 'e' : 'e+') + e;
225
254
  // Normal notation.
226
255
  }
@@ -292,20 +321,31 @@ P.cmp = function (y) {
292
321
  * if necessary, to a maximum of Big.DP decimal places using rounding mode Big.RM.
293
322
  */
294
323
  P.div = function (y) {
295
- var Big = this.constructor, x = new Big(this), y = new Big(y), a = x.c, // dividend
296
- b = y.c, // divisor
297
- k = x.s == y.s ? 1 : -1, dp = Big.DP;
324
+ var Big = this.constructor, dp = Big.DP;
298
325
  if (dp !== ~~dp || dp < 0 || dp > MAX_DP) {
299
326
  throw Error(INVALID_DP);
300
327
  }
328
+ return divide(new Big(this), new Big(y), dp, 2);
329
+ };
330
+ /*
331
+ * Return Big x divided by Big y to dp decimal places using rounding mode rm.
332
+ * Both are modified.
333
+ */
334
+ function divide(x, y, dp, rm) {
335
+ var a = x.c, // dividend
336
+ b = y.c, // divisor
337
+ k = x.s == y.s ? 1 : -1;
301
338
  // Divisor is zero?
302
339
  if (!b[0]) {
303
340
  throw Error(DIV_BY_ZERO);
304
341
  }
342
+ // Scale of the exact quotient is at least the scale of x less the scale of y.
343
+ var minScale = Math.max(0, scaleOf(x) - scaleOf(y));
305
344
  // Dividend is 0? Return +-0.
306
345
  if (!a[0]) {
307
346
  y.s = k;
308
- y.c = [y.e = 0];
347
+ y.c = [0];
348
+ y.e = -minScale;
309
349
  return y;
310
350
  }
311
351
  var bl, bt, n, cmp, ri, bz = b.slice(), ai = bl = b.length, al = a.length, r = a.slice(0, bl), // remainder
@@ -369,11 +409,20 @@ P.div = function (y) {
369
409
  q.e--;
370
410
  p--;
371
411
  }
412
+ var exact = r[0] === UNDEFINED;
372
413
  // Round?
373
414
  if (qi > p)
374
- round(q, p, Big.RM, r[0] !== UNDEFINED);
415
+ round(q, p, rm, !exact);
416
+ fit(q);
417
+ if (!q.c[0]) {
418
+ q.e = 0;
419
+ }
420
+ else if (exact) {
421
+ for (; scaleOf(q) > minScale && !q.c[q.c.length - 1];)
422
+ q.c.pop();
423
+ }
375
424
  return q;
376
- };
425
+ }
377
426
  /*
378
427
  * Return true if the value of this Big is equal to the value of Big y, otherwise return false.
379
428
  */
@@ -420,6 +469,7 @@ P.minus = P.sub = function (y) {
420
469
  var xc = x.c.slice(), xe = x.e, yc = y.c, ye = y.e;
421
470
  // Either zero?
422
471
  if (!xc[0] || !yc[0]) {
472
+ var dp = Math.max(scaleOf(x), scaleOf(y));
423
473
  if (yc[0]) {
424
474
  y.s = -b;
425
475
  }
@@ -429,7 +479,7 @@ P.minus = P.sub = function (y) {
429
479
  else {
430
480
  y.s = 1;
431
481
  }
432
- return y;
482
+ return padScale(y, dp);
433
483
  }
434
484
  // Determine which is the bigger number. Prepend zeros to equalise exponents.
435
485
  if (a = xe - ye) {
@@ -480,9 +530,8 @@ P.minus = P.sub = function (y) {
480
530
  }
481
531
  xc[j] -= yc[j];
482
532
  }
483
- // Remove trailing zeros.
484
- for (; xc[--b] === 0;)
485
- xc.pop();
533
+ // The result keeps the larger scale.
534
+ var dp = xc.length - ye - 1;
486
535
  // Remove leading zeros and adjust exponent accordingly.
487
536
  for (; xc[0] === 0;) {
488
537
  xc.shift();
@@ -492,11 +541,12 @@ P.minus = P.sub = function (y) {
492
541
  // n - n = +0
493
542
  y.s = 1;
494
543
  // Result must be zero.
495
- xc = [ye = 0];
544
+ xc = [0];
545
+ ye = -dp;
496
546
  }
497
547
  y.c = xc;
498
548
  y.e = ye;
499
- return y;
549
+ return fit(y);
500
550
  };
501
551
  /*
502
552
  * Return a new Big whose value is the value of this Big modulo the value of Big y.
@@ -512,12 +562,7 @@ P.mod = function (y) {
512
562
  y.s = b;
513
563
  if (ygtx)
514
564
  return new Big(x);
515
- a = Big.DP;
516
- b = Big.RM;
517
- Big.DP = Big.RM = 0;
518
- x = x.div(y);
519
- Big.DP = a;
520
- Big.RM = b;
565
+ x = divide(x, new Big(y), 0, 0);
521
566
  return this.minus(x.times(y));
522
567
  };
523
568
  /*
@@ -533,6 +578,7 @@ P.plus = P.add = function (y) {
533
578
  var xe = x.e, xc = x.c, ye = y.e, yc = y.c;
534
579
  // Either zero?
535
580
  if (!xc[0] || !yc[0]) {
581
+ var dp = Math.max(scaleOf(x), scaleOf(y));
536
582
  if (!yc[0]) {
537
583
  if (xc[0]) {
538
584
  y = new Big(x);
@@ -541,7 +587,7 @@ P.plus = P.add = function (y) {
541
587
  y.s = x.s;
542
588
  }
543
589
  }
544
- return y;
590
+ return padScale(y, dp);
545
591
  }
546
592
  xc = xc.slice();
547
593
  // Prepend zeros to equalise exponents.
@@ -575,12 +621,9 @@ P.plus = P.add = function (y) {
575
621
  xc.unshift(k);
576
622
  ++ye;
577
623
  }
578
- // Remove trailing zeros.
579
- for (e = xc.length; xc[--e] === 0;)
580
- xc.pop();
581
624
  y.c = xc;
582
625
  y.e = ye;
583
- return y;
626
+ return fit(y);
584
627
  };
585
628
  /*
586
629
  * Return a Big whose value is the value of this Big raised to the power n.
@@ -681,7 +724,9 @@ P.times = P.mul = function (y) {
681
724
  y.s = x.s == y.s ? 1 : -1;
682
725
  // Return signed 0 if either 0.
683
726
  if (!xc[0] || !yc[0]) {
684
- y.c = [y.e = 0];
727
+ var dp = scaleOf(x) + scaleOf(y);
728
+ y.c = [0];
729
+ y.e = -dp;
685
730
  return y;
686
731
  }
687
732
  // Initialise exponent of result as x.e + y.e.
@@ -717,11 +762,8 @@ P.times = P.mul = function (y) {
717
762
  ++y.e;
718
763
  else
719
764
  c.shift();
720
- // Remove trailing zeros.
721
- for (i = c.length; !c[--i];)
722
- c.pop();
723
765
  y.c = c;
724
- return y;
766
+ return fit(y);
725
767
  };
726
768
  /*
727
769
  * Return a string representing the value of this Big in exponential notation rounded to dp fixed
@@ -731,7 +773,7 @@ P.times = P.mul = function (y) {
731
773
  * rm? {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).
732
774
  */
733
775
  P.toExponential = function (dp, rm) {
734
- var x = this, n = hasNonzeroDigit(x);
776
+ var x = this, n = x.c[0];
735
777
  if (dp !== UNDEFINED) {
736
778
  if (dp !== ~~dp || dp < 0 || dp > MAX_DP) {
737
779
  throw Error(INVALID_DP);
@@ -740,7 +782,7 @@ P.toExponential = function (dp, rm) {
740
782
  for (; x.c.length < dp;)
741
783
  x.c.push(0);
742
784
  }
743
- return stringify(x, true, n);
785
+ return stringify(x, true, !!n);
744
786
  };
745
787
  /*
746
788
  * Return a string representing the value of this Big in normal notation rounded to dp fixed
@@ -758,13 +800,12 @@ P.toFixed = function (dp, rm) {
758
800
  if (dp !== ~~dp || dp < 0 || dp > MAX_DP) {
759
801
  throw Error(INVALID_DP);
760
802
  }
761
- x = new x.constructor(x);
762
- x = round(x, dp + x.e + 1, rm);
803
+ x = round(new x.constructor(x), dp + x.e + 1, rm);
763
804
  // x.e may have changed if the value is rounded up.
764
805
  for (dp = dp + x.e + 1; x.c.length < dp;)
765
806
  x.c.push(0);
766
807
  }
767
- return stringify(x, false, hasNonzeroDigit(x));
808
+ return stringify(x, false, !!x.c[0]);
768
809
  };
769
810
  /*
770
811
  * Return a string representing the value of this Big.
@@ -774,7 +815,7 @@ P.toFixed = function (dp, rm) {
774
815
  */
775
816
  P.toJSON = P.toString = function () {
776
817
  var x = this, Big = x.constructor;
777
- return stringify(x, x.e <= Big.NE || x.e >= Big.PE, hasNonzeroDigit(x));
818
+ return stringify(x, x.e <= Big.NE || x.e >= Big.PE, !!x.c[0]);
778
819
  };
779
820
  /*
780
821
  * Return the value of this Big as a primitve number.
@@ -796,16 +837,18 @@ P.toNumber = function () {
796
837
  * rm? {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).
797
838
  */
798
839
  P.toPrecision = function (sd, rm) {
799
- var x = this, Big = x.constructor, n = hasNonzeroDigit(x);
840
+ var x = this, Big = x.constructor, n = x.c[0];
800
841
  if (sd !== UNDEFINED) {
801
842
  if (sd !== ~~sd || sd < 1 || sd > MAX_DP) {
802
843
  throw Error(INVALID + 'precision');
803
844
  }
804
845
  x = round(new Big(x), sd, rm);
846
+ if (!x.c[0])
847
+ x.e = 0;
805
848
  for (; x.c.length < sd;)
806
849
  x.c.push(0);
807
850
  }
808
- return stringify(x, sd <= x.e || x.e <= Big.NE || x.e >= Big.PE, n);
851
+ return stringify(x, sd <= x.e || x.e <= Big.NE || x.e >= Big.PE, !!n);
809
852
  };
810
853
  /*
811
854
  * Return a string representing the value of this Big.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": false,
4
4
  "type": "module",
5
5
  "name": "@fable-org/fable-library-js",
6
- "version": "2.9.0",
6
+ "version": "2.11.0",
7
7
  "description": "Core library used by F# projects compiled with fable.io",
8
8
  "author": "Fable Contributors",
9
9
  "license": "MIT",