@formatjs/ecma402-abstract 2.2.5 → 2.3.1

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.
Files changed (71) hide show
  1. package/262.d.ts +5 -4
  2. package/262.js +13 -17
  3. package/CanonicalizeLocaleList.d.ts +1 -1
  4. package/IsSanctionedSimpleUnitIdentifier.d.ts +1 -1
  5. package/NumberFormat/ApplyUnsignedRoundingMode.d.ts +2 -1
  6. package/NumberFormat/ApplyUnsignedRoundingMode.js +11 -16
  7. package/NumberFormat/ComputeExponent.d.ts +2 -1
  8. package/NumberFormat/ComputeExponent.js +13 -13
  9. package/NumberFormat/ComputeExponentForMagnitude.d.ts +2 -1
  10. package/NumberFormat/ComputeExponentForMagnitude.js +12 -3
  11. package/NumberFormat/FormatNumericRange.d.ts +2 -1
  12. package/NumberFormat/FormatNumericRangeToParts.d.ts +2 -1
  13. package/NumberFormat/FormatNumericToParts.d.ts +2 -1
  14. package/NumberFormat/FormatNumericToParts.js +1 -1
  15. package/NumberFormat/FormatNumericToString.d.ts +3 -2
  16. package/NumberFormat/FormatNumericToString.js +56 -14
  17. package/NumberFormat/InitializeNumberFormat.js +7 -36
  18. package/NumberFormat/PartitionNumberPattern.d.ts +4 -3
  19. package/NumberFormat/PartitionNumberPattern.js +25 -18
  20. package/NumberFormat/PartitionNumberRangePattern.d.ts +2 -1
  21. package/NumberFormat/PartitionNumberRangePattern.js +2 -3
  22. package/NumberFormat/SetNumberFormatDigitOptions.js +53 -24
  23. package/NumberFormat/ToRawFixed.d.ts +3 -2
  24. package/NumberFormat/ToRawFixed.js +55 -18
  25. package/NumberFormat/ToRawPrecision.d.ts +3 -2
  26. package/NumberFormat/ToRawPrecision.js +75 -42
  27. package/NumberFormat/format_to_parts.d.ts +5 -2
  28. package/NumberFormat/format_to_parts.js +35 -20
  29. package/constants.d.ts +4 -0
  30. package/constants.js +8 -0
  31. package/index.d.ts +2 -1
  32. package/index.js +3 -2
  33. package/lib/262.d.ts +5 -4
  34. package/lib/262.js +13 -17
  35. package/lib/CanonicalizeLocaleList.d.ts +1 -1
  36. package/lib/IsSanctionedSimpleUnitIdentifier.d.ts +1 -1
  37. package/lib/NumberFormat/ApplyUnsignedRoundingMode.d.ts +2 -1
  38. package/lib/NumberFormat/ApplyUnsignedRoundingMode.js +11 -16
  39. package/lib/NumberFormat/ComputeExponent.d.ts +2 -1
  40. package/lib/NumberFormat/ComputeExponent.js +13 -13
  41. package/lib/NumberFormat/ComputeExponentForMagnitude.d.ts +2 -1
  42. package/lib/NumberFormat/ComputeExponentForMagnitude.js +11 -3
  43. package/lib/NumberFormat/FormatNumericRange.d.ts +2 -1
  44. package/lib/NumberFormat/FormatNumericRangeToParts.d.ts +2 -1
  45. package/lib/NumberFormat/FormatNumericToParts.d.ts +2 -1
  46. package/lib/NumberFormat/FormatNumericToParts.js +1 -1
  47. package/lib/NumberFormat/FormatNumericToString.d.ts +3 -2
  48. package/lib/NumberFormat/FormatNumericToString.js +57 -15
  49. package/lib/NumberFormat/InitializeNumberFormat.js +7 -36
  50. package/lib/NumberFormat/PartitionNumberPattern.d.ts +4 -3
  51. package/lib/NumberFormat/PartitionNumberPattern.js +25 -18
  52. package/lib/NumberFormat/PartitionNumberRangePattern.d.ts +2 -1
  53. package/lib/NumberFormat/PartitionNumberRangePattern.js +2 -3
  54. package/lib/NumberFormat/SetNumberFormatDigitOptions.js +53 -24
  55. package/lib/NumberFormat/ToRawFixed.d.ts +3 -2
  56. package/lib/NumberFormat/ToRawFixed.js +54 -18
  57. package/lib/NumberFormat/ToRawPrecision.d.ts +3 -2
  58. package/lib/NumberFormat/ToRawPrecision.js +75 -43
  59. package/lib/NumberFormat/format_to_parts.d.ts +5 -2
  60. package/lib/NumberFormat/format_to_parts.js +34 -20
  61. package/lib/constants.d.ts +4 -0
  62. package/lib/constants.js +4 -0
  63. package/lib/index.d.ts +2 -1
  64. package/lib/index.js +2 -1
  65. package/lib/types/number.d.ts +16 -9
  66. package/lib/utils.d.ts +0 -5
  67. package/lib/utils.js +0 -9
  68. package/package.json +4 -3
  69. package/types/number.d.ts +16 -9
  70. package/utils.d.ts +0 -5
  71. package/utils.js +0 -10
@@ -1,47 +1,77 @@
1
- import { repeat, getMagnitude } from '../utils';
2
- export function ToRawPrecision(x, minPrecision, maxPrecision) {
1
+ import Decimal from 'decimal.js';
2
+ import { TEN, ZERO } from '../constants';
3
+ import { invariant, repeat } from '../utils';
4
+ import { ApplyUnsignedRoundingMode } from './ApplyUnsignedRoundingMode';
5
+ Decimal.set({
6
+ toExpPos: 100,
7
+ });
8
+ function ToRawPrecisionFn(n, e, p) {
9
+ invariant(TEN.pow(p - 1).lessThanOrEqualTo(n) && n.lessThan(TEN.pow(p)), "n should be in the range ".concat(TEN.pow(p - 1), " <= n < ").concat(TEN.pow(p), " but got ").concat(n));
10
+ // n * 10^(e - p + 1)
11
+ return n.times(TEN.pow(e.minus(p).plus(1)));
12
+ }
13
+ function findN1E1R1(x, p) {
14
+ var maxN1 = TEN.pow(p);
15
+ var minN1 = TEN.pow(p - 1);
16
+ var maxE1 = x.div(minN1).log(10).plus(p).minus(1).ceil();
17
+ for (var currentE1 = maxE1;; currentE1 = currentE1.minus(1)) {
18
+ var currentN1 = x.div(TEN.pow(currentE1.minus(p).plus(1))).floor();
19
+ if (currentN1.lessThan(maxN1) && currentN1.greaterThanOrEqualTo(minN1)) {
20
+ var currentR1 = ToRawPrecisionFn(currentN1, currentE1, p);
21
+ if (currentR1.lessThanOrEqualTo(x)) {
22
+ return {
23
+ n1: currentN1,
24
+ e1: currentE1,
25
+ r1: currentR1,
26
+ };
27
+ }
28
+ }
29
+ }
30
+ }
31
+ function findN2E2R2(x, p) {
32
+ var maxN2 = TEN.pow(p);
33
+ var minN2 = TEN.pow(p - 1);
34
+ var minE2 = x.div(maxN2).log(10).plus(p).minus(1).floor();
35
+ for (var currentE2 = minE2;; currentE2 = currentE2.plus(1)) {
36
+ var currentN2 = x.div(TEN.pow(currentE2.minus(p).plus(1))).ceil();
37
+ if (currentN2.lessThan(maxN2) && currentN2.greaterThanOrEqualTo(minN2)) {
38
+ var currentR2 = ToRawPrecisionFn(currentN2, currentE2, p);
39
+ if (currentR2.greaterThanOrEqualTo(x)) {
40
+ return {
41
+ n2: currentN2,
42
+ e2: currentE2,
43
+ r2: currentR2,
44
+ };
45
+ }
46
+ }
47
+ }
48
+ }
49
+ export function ToRawPrecision(x, minPrecision, maxPrecision, unsignedRoundingMode) {
3
50
  var p = maxPrecision;
4
51
  var m;
5
52
  var e;
6
53
  var xFinal;
7
- if (x === 0) {
54
+ if (x.isZero()) {
8
55
  m = repeat('0', p);
9
56
  e = 0;
10
- xFinal = 0;
57
+ xFinal = ZERO;
11
58
  }
12
59
  else {
13
- var xToString = x.toString();
14
- // If xToString is formatted as scientific notation, the number is either very small or very
15
- // large. If the precision of the formatted string is lower that requested max precision, we
16
- // should still infer them from the formatted string, otherwise the formatted result might have
17
- // precision loss (e.g. 1e41 will not have 0 in every trailing digits).
18
- var xToStringExponentIndex = xToString.indexOf('e');
19
- var _a = xToString.split('e'), xToStringMantissa = _a[0], xToStringExponent = _a[1];
20
- var xToStringMantissaWithoutDecimalPoint = xToStringMantissa.replace('.', '');
21
- if (xToStringExponentIndex >= 0 &&
22
- xToStringMantissaWithoutDecimalPoint.length <= p) {
23
- e = +xToStringExponent;
24
- m =
25
- xToStringMantissaWithoutDecimalPoint +
26
- repeat('0', p - xToStringMantissaWithoutDecimalPoint.length);
27
- xFinal = x;
60
+ var _a = findN1E1R1(x, p), n1 = _a.n1, e1 = _a.e1, r1 = _a.r1;
61
+ var _b = findN2E2R2(x, p), n2 = _b.n2, e2 = _b.e2, r2 = _b.r2;
62
+ var r = ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode);
63
+ var n = void 0;
64
+ if (r.eq(r1)) {
65
+ n = n1;
66
+ e = e1.toNumber();
67
+ xFinal = r1;
28
68
  }
29
69
  else {
30
- e = getMagnitude(x);
31
- var decimalPlaceOffset = e - p + 1;
32
- // n is the integer containing the required precision digits. To derive the formatted string,
33
- // we will adjust its decimal place in the logic below.
34
- var n = Math.round(adjustDecimalPlace(x, decimalPlaceOffset));
35
- // The rounding caused the change of magnitude, so we should increment `e` by 1.
36
- if (adjustDecimalPlace(n, p - 1) >= 10) {
37
- e = e + 1;
38
- // Divide n by 10 to swallow one precision.
39
- n = Math.floor(n / 10);
40
- }
41
- m = n.toString();
42
- // Equivalent of n * 10 ** (e - p + 1)
43
- xFinal = adjustDecimalPlace(n, p - 1 - e);
70
+ n = n2;
71
+ e = e2.toNumber();
72
+ xFinal = r2;
44
73
  }
74
+ m = n.toString();
45
75
  }
46
76
  var int;
47
77
  if (e >= p - 1) {
@@ -49,26 +79,28 @@ export function ToRawPrecision(x, minPrecision, maxPrecision) {
49
79
  int = e + 1;
50
80
  }
51
81
  else if (e >= 0) {
52
- m = "".concat(m.slice(0, e + 1), ".").concat(m.slice(e + 1));
82
+ m = m.slice(0, e + 1) + '.' + m.slice(m.length - (p - (e + 1)));
53
83
  int = e + 1;
54
84
  }
55
85
  else {
56
- m = "0.".concat(repeat('0', -e - 1)).concat(m);
86
+ invariant(e < 0, 'e should be less than 0');
87
+ m = '0.' + repeat('0', -e - 1) + m;
57
88
  int = 1;
58
89
  }
59
- if (m.indexOf('.') >= 0 && maxPrecision > minPrecision) {
90
+ if (m.includes('.') && maxPrecision > minPrecision) {
60
91
  var cut = maxPrecision - minPrecision;
61
92
  while (cut > 0 && m[m.length - 1] === '0') {
62
- m = m.slice(0, -1);
93
+ m = m.slice(0, m.length - 1);
63
94
  cut--;
64
95
  }
65
96
  if (m[m.length - 1] === '.') {
66
- m = m.slice(0, -1);
97
+ m = m.slice(0, m.length - 1);
67
98
  }
68
99
  }
69
- return { formattedString: m, roundedNumber: xFinal, integerDigitsCount: int };
70
- // x / (10 ** magnitude), but try to preserve as much floating point precision as possible.
71
- function adjustDecimalPlace(x, magnitude) {
72
- return magnitude < 0 ? x * Math.pow(10, -magnitude) : x / Math.pow(10, magnitude);
73
- }
100
+ return {
101
+ formattedString: m,
102
+ roundedNumber: xFinal,
103
+ integerDigitsCount: int,
104
+ roundingMagnitude: e,
105
+ };
74
106
  }
@@ -1,7 +1,8 @@
1
- import { NumberFormatLocaleInternalData, NumberFormatOptionsCompactDisplay, NumberFormatOptionsCurrencyDisplay, NumberFormatOptionsCurrencySign, NumberFormatOptionsNotation, NumberFormatOptionsStyle, NumberFormatOptionsUnitDisplay, NumberFormatPart, UseGroupingType } from '../types/number';
1
+ import Decimal from 'decimal.js';
2
+ import { NumberFormatLocaleInternalData, NumberFormatOptionsCompactDisplay, NumberFormatOptionsCurrencyDisplay, NumberFormatOptionsCurrencySign, NumberFormatOptionsNotation, NumberFormatOptionsStyle, NumberFormatOptionsUnitDisplay, NumberFormatPart, RoundingModeType, UseGroupingType } from '../types/number';
2
3
  interface NumberResult {
3
4
  formattedString: string;
4
- roundedNumber: number;
5
+ roundedNumber: Decimal;
5
6
  sign: -1 | 0 | 1;
6
7
  exponent: number;
7
8
  magnitude: number;
@@ -17,5 +18,7 @@ export default function formatToParts(numberResult: NumberResult, data: NumberFo
17
18
  currencySign?: NumberFormatOptionsCurrencySign;
18
19
  unit?: string;
19
20
  unitDisplay?: NumberFormatOptionsUnitDisplay;
21
+ roundingIncrement: number;
22
+ roundingMode: RoundingModeType;
20
23
  }): NumberFormatPart[];
21
24
  export {};
@@ -1,6 +1,9 @@
1
+ import Decimal from 'decimal.js';
2
+ import { TEN } from '../constants';
1
3
  import { S_UNICODE_REGEX } from '../regex.generated';
2
- import { ToRawFixed } from './ToRawFixed';
3
4
  import { digitMapping } from './digit-mapping.generated';
5
+ import { GetUnsignedRoundingMode } from './GetUnsignedRoundingMode';
6
+ import { ToRawFixed } from './ToRawFixed';
4
7
  // This is from: unicode-12.1.0/General_Category/Symbol/regex.js
5
8
  // IE11 does not support unicode flag, otherwise this is just /\p{S}/u.
6
9
  // /^\p{S}/u
@@ -9,6 +12,7 @@ var CARET_S_UNICODE_REGEX = new RegExp("^".concat(S_UNICODE_REGEX.source));
9
12
  var S_DOLLAR_UNICODE_REGEX = new RegExp("".concat(S_UNICODE_REGEX.source, "$"));
10
13
  var CLDR_NUMBER_PATTERN = /[#0](?:[\.,][#0]+)*/g;
11
14
  export default function formatToParts(numberResult, data, pl, options) {
15
+ var _a;
12
16
  var sign = numberResult.sign, exponent = numberResult.exponent, magnitude = numberResult.magnitude;
13
17
  var notation = options.notation, style = options.style, numberingSystem = options.numberingSystem;
14
18
  var defaultNumberingSystem = data.numbers.nu[0];
@@ -115,9 +119,9 @@ export default function formatToParts(numberResult, data, pl, options) {
115
119
  switch (part) {
116
120
  case '{0}': {
117
121
  // We only need to handle scientific and engineering notation here.
118
- numberParts.push.apply(numberParts, paritionNumberIntoParts(symbols, numberResult, notation, exponent, numberingSystem,
122
+ numberParts.push.apply(numberParts, partitionNumberIntoParts(symbols, numberResult, notation, exponent, numberingSystem,
119
123
  // If compact number pattern exists, do not insert group separators.
120
- !compactNumberPattern && Boolean(options.useGrouping), decimalNumberPattern, style));
124
+ !compactNumberPattern && ((_a = options.useGrouping) !== null && _a !== void 0 ? _a : true), decimalNumberPattern, style, options.roundingIncrement, GetUnsignedRoundingMode(options.roundingMode, sign === -1)));
121
125
  break;
122
126
  }
123
127
  case '-':
@@ -160,7 +164,7 @@ export default function formatToParts(numberResult, data, pl, options) {
160
164
  var unitName = void 0;
161
165
  var currencyNameData = data.currencies[options.currency];
162
166
  if (currencyNameData) {
163
- unitName = selectPlural(pl, numberResult.roundedNumber * Math.pow(10, exponent), currencyNameData.displayName);
167
+ unitName = selectPlural(pl, numberResult.roundedNumber.times(TEN.pow(exponent)).toNumber(), currencyNameData.displayName);
164
168
  }
165
169
  else {
166
170
  // Fallback for unknown currency
@@ -169,8 +173,8 @@ export default function formatToParts(numberResult, data, pl, options) {
169
173
  // Do {0} and {1} substitution
170
174
  var unitPatternParts = unitPattern.split(/(\{[01]\})/g);
171
175
  var result = [];
172
- for (var _a = 0, unitPatternParts_1 = unitPatternParts; _a < unitPatternParts_1.length; _a++) {
173
- var part = unitPatternParts_1[_a];
176
+ for (var _b = 0, unitPatternParts_1 = unitPatternParts; _b < unitPatternParts_1.length; _b++) {
177
+ var part = unitPatternParts_1[_b];
174
178
  switch (part) {
175
179
  case '{0}':
176
180
  result.push.apply(result, numberParts);
@@ -197,15 +201,15 @@ export default function formatToParts(numberResult, data, pl, options) {
197
201
  var unitPattern = void 0;
198
202
  if (unitData) {
199
203
  // Simple unit pattern
200
- unitPattern = selectPlural(pl, numberResult.roundedNumber * Math.pow(10, exponent), data.units.simple[unit][unitDisplay]);
204
+ unitPattern = selectPlural(pl, numberResult.roundedNumber.times(TEN.pow(exponent)).toNumber(), data.units.simple[unit][unitDisplay]);
201
205
  }
202
206
  else {
203
207
  // See: http://unicode.org/reports/tr35/tr35-general.html#perUnitPatterns
204
208
  // If cannot find unit in the simple pattern, it must be "per" compound pattern.
205
209
  // Implementation note: we are not following TR-35 here because we need to format to parts!
206
- var _b = unit.split('-per-'), numeratorUnit = _b[0], denominatorUnit = _b[1];
210
+ var _c = unit.split('-per-'), numeratorUnit = _c[0], denominatorUnit = _c[1];
207
211
  unitData = data.units.simple[numeratorUnit];
208
- var numeratorUnitPattern = selectPlural(pl, numberResult.roundedNumber * Math.pow(10, exponent), data.units.simple[numeratorUnit][unitDisplay]);
212
+ var numeratorUnitPattern = selectPlural(pl, numberResult.roundedNumber.times(TEN.pow(exponent)).toNumber(), data.units.simple[numeratorUnit][unitDisplay]);
209
213
  var perUnitPattern = data.units.simple[denominatorUnit].perUnit[unitDisplay];
210
214
  if (perUnitPattern) {
211
215
  // perUnitPattern exists, combine it with numeratorUnitPattern
@@ -223,8 +227,8 @@ export default function formatToParts(numberResult, data, pl, options) {
223
227
  }
224
228
  var result = [];
225
229
  // We need spacing around "{0}" because they are not treated as "unit" parts, but "literal".
226
- for (var _c = 0, _d = unitPattern.split(/(\s*\{0\}\s*)/); _c < _d.length; _c++) {
227
- var part = _d[_c];
230
+ for (var _d = 0, _e = unitPattern.split(/(\s*\{0\}\s*)/); _d < _e.length; _d++) {
231
+ var part = _e[_d];
228
232
  var interpolateMatch = /^(\s*)\{0\}(\s*)$/.exec(part);
229
233
  if (interpolateMatch) {
230
234
  // Space before "{0}"
@@ -251,7 +255,7 @@ export default function formatToParts(numberResult, data, pl, options) {
251
255
  }
252
256
  // A subset of https://tc39.es/ecma402/#sec-partitionnotationsubpattern
253
257
  // Plus the exponent parts handling.
254
- function paritionNumberIntoParts(symbols, numberResult, notation, exponent, numberingSystem, useGrouping,
258
+ function partitionNumberIntoParts(symbols, numberResult, notation, exponent, numberingSystem, useGrouping,
255
259
  /**
256
260
  * This is the decimal number pattern without signs or symbols.
257
261
  * It is used to infer the group size when `useGrouping` is true.
@@ -259,14 +263,14 @@ function paritionNumberIntoParts(symbols, numberResult, notation, exponent, numb
259
263
  * A typical value looks like "#,##0.00" (primary group size is 3).
260
264
  * Some locales like Hindi has secondary group size of 2 (e.g. "#,##,##0.00").
261
265
  */
262
- decimalNumberPattern, style) {
266
+ decimalNumberPattern, style, roundingIncrement, unsignedRoundingMode) {
263
267
  var result = [];
264
268
  // eslint-disable-next-line prefer-const
265
269
  var n = numberResult.formattedString, x = numberResult.roundedNumber;
266
- if (isNaN(x)) {
270
+ if (x.isNaN()) {
267
271
  return [{ type: 'nan', value: n }];
268
272
  }
269
- else if (!isFinite(x)) {
273
+ else if (!x.isFinite()) {
270
274
  return [{ type: 'infinity', value: n }];
271
275
  }
272
276
  var digitReplacementTable = digitMapping[numberingSystem];
@@ -291,7 +295,17 @@ decimalNumberPattern, style) {
291
295
  // unless the rounded number is greater than 10000:
292
296
  // NumberFormat('de', {notation: 'compact', compactDisplay: 'short'}).format(1234) //=> "1234"
293
297
  // NumberFormat('de').format(1234) //=> "1.234"
294
- if (useGrouping && (notation !== 'compact' || x >= 10000)) {
298
+ var shouldUseGrouping = false;
299
+ if (useGrouping === 'always') {
300
+ shouldUseGrouping = true;
301
+ }
302
+ else if (useGrouping === 'min2') {
303
+ shouldUseGrouping = x.greaterThanOrEqualTo(10000);
304
+ }
305
+ else if (useGrouping === 'auto' || useGrouping) {
306
+ shouldUseGrouping = notation !== 'compact' || x.greaterThanOrEqualTo(10000);
307
+ }
308
+ if (shouldUseGrouping) {
295
309
  // a. Let groupSepSymbol be the implementation-, locale-, and numbering system-dependent (ILND) String representing the grouping separator.
296
310
  // For currency we should use `currencyGroup` instead of generic `group`
297
311
  var groupSepSymbol = style === 'currency' && symbols.currencyGroup != null
@@ -346,13 +360,13 @@ decimalNumberPattern, style) {
346
360
  result.push({ type: 'decimal', value: decimalSepSymbol }, { type: 'fraction', value: fraction });
347
361
  }
348
362
  if ((notation === 'scientific' || notation === 'engineering') &&
349
- isFinite(x)) {
363
+ x.isFinite()) {
350
364
  result.push({ type: 'exponentSeparator', value: symbols.exponential });
351
365
  if (exponent < 0) {
352
366
  result.push({ type: 'exponentMinusSign', value: symbols.minusSign });
353
367
  exponent = -exponent;
354
368
  }
355
- var exponentResult = ToRawFixed(exponent, 0, 0);
369
+ var exponentResult = ToRawFixed(new Decimal(exponent), 0, 0, roundingIncrement, unsignedRoundingMode);
356
370
  result.push({
357
371
  type: 'exponentInteger',
358
372
  value: exponentResult.formattedString,
@@ -398,7 +412,7 @@ function getCompactDisplayPattern(numberResult, pl, data, style, compactDisplay,
398
412
  if (!compactPluralRules) {
399
413
  return null;
400
414
  }
401
- pattern = selectPlural(pl, roundedNumber, compactPluralRules);
415
+ pattern = selectPlural(pl, roundedNumber.toNumber(), compactPluralRules);
402
416
  }
403
417
  else {
404
418
  var byNumberingSystem = data.numbers.decimal;
@@ -408,7 +422,7 @@ function getCompactDisplayPattern(numberResult, pl, data, style, compactDisplay,
408
422
  if (!compactPlaralRule) {
409
423
  return null;
410
424
  }
411
- pattern = selectPlural(pl, roundedNumber, compactPlaralRule);
425
+ pattern = selectPlural(pl, roundedNumber.toNumber(), compactPlaralRule);
412
426
  }
413
427
  // See https://unicode.org/reports/tr35/tr35-numbers.html#Compact_Number_Formats
414
428
  // > If the value is precisely “0”, either explicit or defaulted, then the normal number format
@@ -0,0 +1,4 @@
1
+ import Decimal from 'decimal.js';
2
+ export declare const TEN: Decimal;
3
+ export declare const ZERO: Decimal;
4
+ export declare const NEGATIVE_ZERO: Decimal;
@@ -0,0 +1,4 @@
1
+ import Decimal from 'decimal.js';
2
+ export var TEN = new Decimal(10);
3
+ export var ZERO = new Decimal(0);
4
+ export var NEGATIVE_ZERO = new Decimal(-0);
package/lib/index.d.ts CHANGED
@@ -30,7 +30,7 @@ export * from './NumberFormat/ToRawFixed';
30
30
  export * from './NumberFormat/ToRawPrecision';
31
31
  export * from './PartitionPattern';
32
32
  export * from './SupportedLocales';
33
- export { createDataProperty, defineProperty, getInternalSlot, getMagnitude, getMultiInternalSlots, isLiteralPart, setInternalSlot, setMultiInternalSlots, } from './utils';
33
+ export { createDataProperty, defineProperty, getInternalSlot, getMultiInternalSlots, isLiteralPart, setInternalSlot, setMultiInternalSlots, } from './utils';
34
34
  export type { LiteralPart } from './utils';
35
35
  export * from './262';
36
36
  export { isMissingLocaleDataError } from './data';
@@ -42,3 +42,4 @@ export * from './types/number';
42
42
  export * from './types/plural-rules';
43
43
  export * from './types/relative-time';
44
44
  export { createMemoizedDateTimeFormat, createMemoizedListFormat, createMemoizedLocale, createMemoizedNumberFormat, createMemoizedPluralRules, invariant, } from './utils';
45
+ export { ZERO } from './constants';
package/lib/index.js CHANGED
@@ -30,7 +30,7 @@ export * from './NumberFormat/ToRawFixed';
30
30
  export * from './NumberFormat/ToRawPrecision';
31
31
  export * from './PartitionPattern';
32
32
  export * from './SupportedLocales';
33
- export { createDataProperty, defineProperty, getInternalSlot, getMagnitude, getMultiInternalSlots, isLiteralPart, setInternalSlot, setMultiInternalSlots, } from './utils';
33
+ export { createDataProperty, defineProperty, getInternalSlot, getMultiInternalSlots, isLiteralPart, setInternalSlot, setMultiInternalSlots, } from './utils';
34
34
  export * from './262';
35
35
  export { isMissingLocaleDataError } from './data';
36
36
  export * from './types/date-time';
@@ -40,3 +40,4 @@ export * from './types/number';
40
40
  export * from './types/plural-rules';
41
41
  export * from './types/relative-time';
42
42
  export { createMemoizedDateTimeFormat, createMemoizedListFormat, createMemoizedLocale, createMemoizedNumberFormat, createMemoizedPluralRules, invariant, } from './utils';
43
+ export { ZERO } from './constants';
@@ -1,3 +1,4 @@
1
+ import Decimal from 'decimal.js';
1
2
  import { LocaleData } from './core';
2
3
  import { LDMLPluralRule } from './plural-rules';
3
4
  export type NumberFormatNotation = 'standard' | 'scientific' | 'engineering' | 'compact';
@@ -13,17 +14,22 @@ export interface NumberFormatDigitOptions {
13
14
  minimumFractionDigits?: number;
14
15
  maximumFractionDigits?: number;
15
16
  roundingPriority?: RoundingPriorityType;
17
+ roundingIncrement?: number;
18
+ roundingMode?: RoundingModeType;
19
+ trailingZeroDisplay?: TrailingZeroDisplay;
16
20
  }
17
21
  export interface NumberFormatDigitInternalSlots {
18
22
  minimumIntegerDigits: number;
19
- minimumSignificantDigits?: number;
20
- maximumSignificantDigits?: number;
23
+ minimumSignificantDigits: number;
24
+ maximumSignificantDigits: number;
21
25
  roundingType: NumberFormatRoundingType;
22
- minimumFractionDigits?: number;
23
- maximumFractionDigits?: number;
24
- notation?: NumberFormatNotation;
25
- roundingIncrement?: number;
26
- trailingZeroDisplay?: TrailingZeroDisplay;
26
+ minimumFractionDigits: number;
27
+ maximumFractionDigits: number;
28
+ notation: NumberFormatNotation;
29
+ roundingIncrement: number;
30
+ roundingMode: RoundingModeType;
31
+ trailingZeroDisplay: TrailingZeroDisplay;
32
+ roundingPriority: RoundingPriorityType;
27
33
  }
28
34
  export type RawNumberLocaleData = LocaleData<NumberFormatLocaleInternalData>;
29
35
  export interface NumberFormatLocaleInternalData {
@@ -106,8 +112,9 @@ export type LDMLPluralRuleMap<T> = Omit<Partial<Record<LDMLPluralRule, T>>, 'oth
106
112
  };
107
113
  export interface RawNumberFormatResult {
108
114
  formattedString: string;
109
- roundedNumber: number;
115
+ roundedNumber: Decimal;
110
116
  integerDigitsCount: number;
117
+ roundingMagnitude: number;
111
118
  }
112
119
  export type NumberFormatOptionsLocaleMatcher = 'lookup' | 'best fit';
113
120
  export type NumberFormatOptionsStyle = 'decimal' | 'percent' | 'currency' | 'unit';
@@ -135,7 +142,7 @@ export interface NumberFormatInternal extends NumberFormatDigitInternalSlots {
135
142
  boundFormat?: Intl.NumberFormat['format'];
136
143
  numberingSystem: string;
137
144
  dataLocaleData: NumberFormatLocaleInternalData;
138
- roundingMode?: RoundingModeType;
145
+ roundingMode: RoundingModeType;
139
146
  }
140
147
  export type NumberFormatOptions = Omit<Intl.NumberFormatOptions, 'signDisplay' | 'useGrouping'> & NumberFormatDigitOptions & {
141
148
  localeMatcher?: NumberFormatOptionsLocaleMatcher;
package/lib/utils.d.ts CHANGED
@@ -1,8 +1,3 @@
1
- /**
2
- * Cannot do Math.log(x) / Math.log(10) bc if IEEE floating point issue
3
- * @param x number
4
- */
5
- export declare function getMagnitude(x: number): number;
6
1
  export declare function repeat(s: string, times: number): string;
7
2
  export declare function setInternalSlot<Instance extends object, Internal extends object, Field extends keyof Internal>(map: WeakMap<Instance, Internal>, pl: Instance, field: Field, value: NonNullable<Internal>[Field]): void;
8
3
  export declare function setMultiInternalSlots<Instance extends object, Internal extends object, K extends keyof Internal>(map: WeakMap<Instance, Internal>, pl: Instance, props: Pick<NonNullable<Internal>, K>): void;
package/lib/utils.js CHANGED
@@ -1,14 +1,5 @@
1
1
  import { __spreadArray } from "tslib";
2
2
  import { memoize, strategies } from '@formatjs/fast-memoize';
3
- /**
4
- * Cannot do Math.log(x) / Math.log(10) bc if IEEE floating point issue
5
- * @param x number
6
- */
7
- export function getMagnitude(x) {
8
- // Cannot count string length via Number.toString because it may use scientific notation
9
- // for very small or very large numbers.
10
- return Math.floor(Math.log(x) * Math.LOG10E);
11
- }
12
3
  export function repeat(s, times) {
13
4
  if (typeof s.repeat === 'function') {
14
5
  return s.repeat(times);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formatjs/ecma402-abstract",
3
- "version": "2.2.5",
3
+ "version": "2.3.1",
4
4
  "description": "A collection of implementation for ECMAScript abstract operations",
5
5
  "keywords": [
6
6
  "intl",
@@ -14,9 +14,10 @@
14
14
  "format"
15
15
  ],
16
16
  "dependencies": {
17
+ "decimal.js": "10",
17
18
  "tslib": "2",
18
- "@formatjs/fast-memoize": "2.2.4",
19
- "@formatjs/intl-localematcher": "0.5.8"
19
+ "@formatjs/intl-localematcher": "0.5.9",
20
+ "@formatjs/fast-memoize": "2.2.5"
20
21
  },
21
22
  "author": "Long Ho <holevietlong@gmail.com",
22
23
  "bugs": {
package/types/number.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import Decimal from 'decimal.js';
1
2
  import { LocaleData } from './core';
2
3
  import { LDMLPluralRule } from './plural-rules';
3
4
  export type NumberFormatNotation = 'standard' | 'scientific' | 'engineering' | 'compact';
@@ -13,17 +14,22 @@ export interface NumberFormatDigitOptions {
13
14
  minimumFractionDigits?: number;
14
15
  maximumFractionDigits?: number;
15
16
  roundingPriority?: RoundingPriorityType;
17
+ roundingIncrement?: number;
18
+ roundingMode?: RoundingModeType;
19
+ trailingZeroDisplay?: TrailingZeroDisplay;
16
20
  }
17
21
  export interface NumberFormatDigitInternalSlots {
18
22
  minimumIntegerDigits: number;
19
- minimumSignificantDigits?: number;
20
- maximumSignificantDigits?: number;
23
+ minimumSignificantDigits: number;
24
+ maximumSignificantDigits: number;
21
25
  roundingType: NumberFormatRoundingType;
22
- minimumFractionDigits?: number;
23
- maximumFractionDigits?: number;
24
- notation?: NumberFormatNotation;
25
- roundingIncrement?: number;
26
- trailingZeroDisplay?: TrailingZeroDisplay;
26
+ minimumFractionDigits: number;
27
+ maximumFractionDigits: number;
28
+ notation: NumberFormatNotation;
29
+ roundingIncrement: number;
30
+ roundingMode: RoundingModeType;
31
+ trailingZeroDisplay: TrailingZeroDisplay;
32
+ roundingPriority: RoundingPriorityType;
27
33
  }
28
34
  export type RawNumberLocaleData = LocaleData<NumberFormatLocaleInternalData>;
29
35
  export interface NumberFormatLocaleInternalData {
@@ -106,8 +112,9 @@ export type LDMLPluralRuleMap<T> = Omit<Partial<Record<LDMLPluralRule, T>>, 'oth
106
112
  };
107
113
  export interface RawNumberFormatResult {
108
114
  formattedString: string;
109
- roundedNumber: number;
115
+ roundedNumber: Decimal;
110
116
  integerDigitsCount: number;
117
+ roundingMagnitude: number;
111
118
  }
112
119
  export type NumberFormatOptionsLocaleMatcher = 'lookup' | 'best fit';
113
120
  export type NumberFormatOptionsStyle = 'decimal' | 'percent' | 'currency' | 'unit';
@@ -135,7 +142,7 @@ export interface NumberFormatInternal extends NumberFormatDigitInternalSlots {
135
142
  boundFormat?: Intl.NumberFormat['format'];
136
143
  numberingSystem: string;
137
144
  dataLocaleData: NumberFormatLocaleInternalData;
138
- roundingMode?: RoundingModeType;
145
+ roundingMode: RoundingModeType;
139
146
  }
140
147
  export type NumberFormatOptions = Omit<Intl.NumberFormatOptions, 'signDisplay' | 'useGrouping'> & NumberFormatDigitOptions & {
141
148
  localeMatcher?: NumberFormatOptionsLocaleMatcher;
package/utils.d.ts CHANGED
@@ -1,8 +1,3 @@
1
- /**
2
- * Cannot do Math.log(x) / Math.log(10) bc if IEEE floating point issue
3
- * @param x number
4
- */
5
- export declare function getMagnitude(x: number): number;
6
1
  export declare function repeat(s: string, times: number): string;
7
2
  export declare function setInternalSlot<Instance extends object, Internal extends object, Field extends keyof Internal>(map: WeakMap<Instance, Internal>, pl: Instance, field: Field, value: NonNullable<Internal>[Field]): void;
8
3
  export declare function setMultiInternalSlots<Instance extends object, Internal extends object, K extends keyof Internal>(map: WeakMap<Instance, Internal>, pl: Instance, props: Pick<NonNullable<Internal>, K>): void;
package/utils.js CHANGED
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createMemoizedListFormat = exports.createMemoizedLocale = exports.createMemoizedPluralRules = exports.createMemoizedDateTimeFormat = exports.createMemoizedNumberFormat = exports.UNICODE_EXTENSION_SEQUENCE_REGEX = void 0;
4
- exports.getMagnitude = getMagnitude;
5
4
  exports.repeat = repeat;
6
5
  exports.setInternalSlot = setInternalSlot;
7
6
  exports.setMultiInternalSlots = setMultiInternalSlots;
@@ -13,15 +12,6 @@ exports.createDataProperty = createDataProperty;
13
12
  exports.invariant = invariant;
14
13
  var tslib_1 = require("tslib");
15
14
  var fast_memoize_1 = require("@formatjs/fast-memoize");
16
- /**
17
- * Cannot do Math.log(x) / Math.log(10) bc if IEEE floating point issue
18
- * @param x number
19
- */
20
- function getMagnitude(x) {
21
- // Cannot count string length via Number.toString because it may use scientific notation
22
- // for very small or very large numbers.
23
- return Math.floor(Math.log(x) * Math.LOG10E);
24
- }
25
15
  function repeat(s, times) {
26
16
  if (typeof s.repeat === 'function') {
27
17
  return s.repeat(times);