@formatjs/ecma402-abstract 2.3.1 → 2.3.2

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 (59) hide show
  1. package/262.d.ts +3 -2
  2. package/262.js +77 -15
  3. package/NumberFormat/ComputeExponent.d.ts +1 -3
  4. package/NumberFormat/ComputeExponent.js +7 -11
  5. package/NumberFormat/ComputeExponentForMagnitude.d.ts +1 -3
  6. package/NumberFormat/ComputeExponentForMagnitude.js +2 -5
  7. package/NumberFormat/FormatApproximately.d.ts +1 -3
  8. package/NumberFormat/FormatApproximately.js +1 -3
  9. package/NumberFormat/FormatNumeric.d.ts +3 -0
  10. package/NumberFormat/FormatNumeric.js +8 -0
  11. package/NumberFormat/FormatNumericToParts.js +1 -1
  12. package/NumberFormat/FormatNumericToString.d.ts +1 -1
  13. package/NumberFormat/FormatNumericToString.js +2 -1
  14. package/NumberFormat/InitializeNumberFormat.js +1 -1
  15. package/NumberFormat/PartitionNumberPattern.d.ts +2 -4
  16. package/NumberFormat/PartitionNumberPattern.js +53 -14
  17. package/NumberFormat/PartitionNumberRangePattern.js +27 -19
  18. package/NumberFormat/SetNumberFormatDigitOptions.js +73 -3
  19. package/NumberFormat/SetNumberFormatUnitOptions.d.ts +1 -3
  20. package/NumberFormat/SetNumberFormatUnitOptions.js +26 -15
  21. package/NumberFormat/ToRawFixed.d.ts +2 -3
  22. package/NumberFormat/ToRawFixed.js +39 -7
  23. package/NumberFormat/ToRawPrecision.d.ts +6 -0
  24. package/NumberFormat/ToRawPrecision.js +61 -19
  25. package/NumberFormat/format_to_parts.js +9 -4
  26. package/ToIntlMathematicalValue.d.ts +2 -0
  27. package/ToIntlMathematicalValue.js +31 -0
  28. package/index.d.ts +2 -0
  29. package/index.js +4 -1
  30. package/lib/262.d.ts +3 -2
  31. package/lib/262.js +76 -15
  32. package/lib/NumberFormat/ComputeExponent.d.ts +1 -3
  33. package/lib/NumberFormat/ComputeExponent.js +6 -11
  34. package/lib/NumberFormat/ComputeExponentForMagnitude.d.ts +1 -3
  35. package/lib/NumberFormat/ComputeExponentForMagnitude.js +2 -5
  36. package/lib/NumberFormat/FormatApproximately.d.ts +1 -3
  37. package/lib/NumberFormat/FormatApproximately.js +1 -3
  38. package/lib/NumberFormat/FormatNumeric.d.ts +3 -0
  39. package/lib/NumberFormat/FormatNumeric.js +5 -0
  40. package/lib/NumberFormat/FormatNumericToParts.js +1 -1
  41. package/lib/NumberFormat/FormatNumericToString.d.ts +1 -1
  42. package/lib/NumberFormat/FormatNumericToString.js +2 -1
  43. package/lib/NumberFormat/InitializeNumberFormat.js +1 -1
  44. package/lib/NumberFormat/PartitionNumberPattern.d.ts +2 -4
  45. package/lib/NumberFormat/PartitionNumberPattern.js +53 -14
  46. package/lib/NumberFormat/PartitionNumberRangePattern.js +27 -19
  47. package/lib/NumberFormat/SetNumberFormatDigitOptions.js +73 -3
  48. package/lib/NumberFormat/SetNumberFormatUnitOptions.d.ts +1 -3
  49. package/lib/NumberFormat/SetNumberFormatUnitOptions.js +26 -15
  50. package/lib/NumberFormat/ToRawFixed.d.ts +2 -3
  51. package/lib/NumberFormat/ToRawFixed.js +39 -7
  52. package/lib/NumberFormat/ToRawPrecision.d.ts +6 -0
  53. package/lib/NumberFormat/ToRawPrecision.js +62 -20
  54. package/lib/NumberFormat/format_to_parts.js +9 -4
  55. package/lib/ToIntlMathematicalValue.d.ts +2 -0
  56. package/lib/ToIntlMathematicalValue.js +27 -0
  57. package/lib/index.d.ts +2 -0
  58. package/lib/index.js +2 -0
  59. package/package.json +3 -3
@@ -2,6 +2,7 @@ import { DefaultNumberOption } from '../DefaultNumberOption';
2
2
  import { GetNumberOption } from '../GetNumberOption';
3
3
  import { GetOption } from '../GetOption';
4
4
  import { invariant } from '../utils';
5
+ //IMPL: Valid rounding increments as per implementation
5
6
  var VALID_ROUNDING_INCREMENTS = new Set([
6
7
  1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000,
7
8
  ]);
@@ -9,14 +10,23 @@ var VALID_ROUNDING_INCREMENTS = new Set([
9
10
  * https://tc39.es/ecma402/#sec-setnfdigitoptions
10
11
  */
11
12
  export function SetNumberFormatDigitOptions(internalSlots, opts, mnfdDefault, mxfdDefault, notation) {
13
+ // 1. Let mnid be ? GetNumberOption(opts, "minimumIntegerDigits", 1, 21, 1).
12
14
  var mnid = GetNumberOption(opts, 'minimumIntegerDigits', 1, 21, 1);
15
+ // 2. Let mnfd be opts.[[MinimumFractionDigits]].
13
16
  var mnfd = opts.minimumFractionDigits;
17
+ // 3. Let mxfd be opts.[[MaximumFractionDigits]].
14
18
  var mxfd = opts.maximumFractionDigits;
19
+ // 4. Let mnsd be opts.[[MinimumSignificantDigits]].
15
20
  var mnsd = opts.minimumSignificantDigits;
21
+ // 5. Let mxsd be opts.[[MaximumSignificantDigits]].
16
22
  var mxsd = opts.maximumSignificantDigits;
23
+ // 6. Set internalSlots.[[MinimumIntegerDigits]] to mnid.
17
24
  internalSlots.minimumIntegerDigits = mnid;
25
+ // 7. Let roundingIncrement be ? GetNumberOption(opts, "roundingIncrement", 1, 5000, 1).
18
26
  var roundingIncrement = GetNumberOption(opts, 'roundingIncrement', 1, 5000, 1);
27
+ // 8. If roundingIncrement is not an element of the list {1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000}, throw a RangeError exception.
19
28
  invariant(VALID_ROUNDING_INCREMENTS.has(roundingIncrement), "Invalid rounding increment value: ".concat(roundingIncrement, ".\nValid values are ").concat(Array.from(VALID_ROUNDING_INCREMENTS).join(', '), "."));
29
+ // 9. Let roundingMode be ? GetOption(opts, "roundingMode", "string", « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfExpand").
20
30
  var roundingMode = GetOption(opts, 'roundingMode', 'string', [
21
31
  'ceil',
22
32
  'floor',
@@ -28,82 +38,142 @@ export function SetNumberFormatDigitOptions(internalSlots, opts, mnfdDefault, mx
28
38
  'halfTrunc',
29
39
  'halfEven',
30
40
  ], 'halfExpand');
41
+ // 10. Let roundingPriority be ? GetOption(opts, "roundingPriority", "string", « "auto", "morePrecision", "lessPrecision" », "auto").
31
42
  var roundingPriority = GetOption(opts, 'roundingPriority', 'string', ['auto', 'morePrecision', 'lessPrecision'], 'auto');
43
+ // 11. Let trailingZeroDisplay be ? GetOption(opts, "trailingZeroDisplay", "string", « "auto", "stripIfInteger" », "auto").
32
44
  var trailingZeroDisplay = GetOption(opts, 'trailingZeroDisplay', 'string', ['auto', 'stripIfInteger'], 'auto');
45
+ // 12. If roundingIncrement is not 1, then
33
46
  if (roundingIncrement !== 1) {
47
+ // 12.a. Set mxfdDefault to mnfdDefault.
34
48
  mxfdDefault = mnfdDefault;
35
49
  }
50
+ // 13. Set internalSlots.[[RoundingIncrement]] to roundingIncrement.
36
51
  internalSlots.roundingIncrement = roundingIncrement;
52
+ // 14. Set internalSlots.[[RoundingMode]] to roundingMode.
37
53
  internalSlots.roundingMode = roundingMode;
54
+ // 15. Set internalSlots.[[TrailingZeroDisplay]] to trailingZeroDisplay.
38
55
  internalSlots.trailingZeroDisplay = trailingZeroDisplay;
56
+ // 16. Let hasSd be true if mnsd is not undefined or mxsd is not undefined; otherwise, let hasSd be false.
39
57
  var hasSd = mnsd !== undefined || mxsd !== undefined;
58
+ // 17. Let hasFd be true if mnfd is not undefined or mxfd is not undefined; otherwise, let hasFd be false.
40
59
  var hasFd = mnfd !== undefined || mxfd !== undefined;
60
+ // 18. Let needSd be true.
41
61
  var needSd = true;
62
+ // 19. Let needFd be true.
42
63
  var needFd = true;
64
+ // 20. If roundingPriority is "auto", then
43
65
  if (roundingPriority === 'auto') {
66
+ // 20.a. Set needSd to hasSd.
44
67
  needSd = hasSd;
68
+ // 20.b. If hasSd is true or hasFd is false and notation is "compact", then
45
69
  if (hasSd || (!hasFd && notation === 'compact')) {
70
+ // 20.b.i. Set needFd to false.
46
71
  needFd = false;
47
72
  }
48
73
  }
74
+ // 21. If needSd is true, then
49
75
  if (needSd) {
76
+ // 21.a. If hasSd is true, then
50
77
  if (hasSd) {
78
+ // 21.a.i. Set internalSlots.[[MinimumSignificantDigits]] to ? DefaultNumberOption(mnsd, 1, 21, 1).
51
79
  internalSlots.minimumSignificantDigits = DefaultNumberOption(mnsd, 1, 21, 1);
80
+ // 21.a.ii. Set internalSlots.[[MaximumSignificantDigits]] to ? DefaultNumberOption(mxsd, internalSlots.[[MinimumSignificantDigits]], 21, 21).
52
81
  internalSlots.maximumSignificantDigits = DefaultNumberOption(mxsd, internalSlots.minimumSignificantDigits, 21, 21);
53
82
  }
54
83
  else {
84
+ // 21.b. Else,
85
+ // 21.b.i. Set internalSlots.[[MinimumSignificantDigits]] to 1.
55
86
  internalSlots.minimumSignificantDigits = 1;
87
+ // 21.b.ii. Set internalSlots.[[MaximumSignificantDigits]] to 21.
56
88
  internalSlots.maximumSignificantDigits = 21;
57
89
  }
58
90
  }
91
+ // 22. If needFd is true, then
59
92
  if (needFd) {
93
+ // 22.a. If hasFd is true, then
60
94
  if (hasFd) {
95
+ // 22.a.i. Set mnfd to ? DefaultNumberOption(mnfd, 0, 100, undefined).
61
96
  mnfd = DefaultNumberOption(mnfd, 0, 100, undefined);
97
+ // 22.a.ii. Set mxfd to ? DefaultNumberOption(mxfd, 0, 100, undefined).
62
98
  mxfd = DefaultNumberOption(mxfd, 0, 100, undefined);
99
+ // 22.a.iii. If mnfd is undefined, then
63
100
  if (mnfd === undefined) {
64
- mnfd = Math.min(mnfdDefault, mxfd !== null && mxfd !== void 0 ? mxfd : 0);
101
+ // 22.a.iii.1. Assert: mxfd is not undefined.
102
+ invariant(mxfd !== undefined, 'maximumFractionDigits must be defined');
103
+ // 22.a.iii.2. Set mnfd to min(mnfdDefault, mxfd).
104
+ mnfd = Math.min(mnfdDefault, mxfd);
65
105
  }
66
106
  else if (mxfd === undefined) {
107
+ // 22.a.iv. Else if mxfd is undefined, then
108
+ // 22.a.iv.1. Set mxfd to max(mxfdDefault, mnfd).
67
109
  mxfd = Math.max(mxfdDefault, mnfd);
68
110
  }
69
111
  else if (mnfd > mxfd) {
112
+ // 22.a.v. Else if mnfd > mxfd, throw a RangeError exception.
70
113
  throw new RangeError("Invalid range, ".concat(mnfd, " > ").concat(mxfd));
71
114
  }
115
+ // 22.a.vi. Set internalSlots.[[MinimumFractionDigits]] to mnfd.
72
116
  internalSlots.minimumFractionDigits = mnfd;
117
+ // 22.a.vii. Set internalSlots.[[MaximumFractionDigits]] to mxfd.
73
118
  internalSlots.maximumFractionDigits = mxfd;
74
119
  }
75
120
  else {
121
+ // 22.b. Else,
122
+ // 22.b.i. Set internalSlots.[[MinimumFractionDigits]] to mnfdDefault.
76
123
  internalSlots.minimumFractionDigits = mnfdDefault;
124
+ // 22.b.ii. Set internalSlots.[[MaximumFractionDigits]] to mxfdDefault.
77
125
  internalSlots.maximumFractionDigits = mxfdDefault;
78
126
  }
79
127
  }
128
+ // 23. If needSd is false and needFd is false, then
80
129
  if (!needSd && !needFd) {
130
+ // 23.a. Set internalSlots.[[MinimumFractionDigits]] to 0.
81
131
  internalSlots.minimumFractionDigits = 0;
132
+ // 23.b. Set internalSlots.[[MaximumFractionDigits]] to 0.
82
133
  internalSlots.maximumFractionDigits = 0;
134
+ // 23.c. Set internalSlots.[[MinimumSignificantDigits]] to 1.
83
135
  internalSlots.minimumSignificantDigits = 1;
136
+ // 23.d. Set internalSlots.[[MaximumSignificantDigits]] to 2.
84
137
  internalSlots.maximumSignificantDigits = 2;
138
+ // 23.e. Set internalSlots.[[RoundingType]] to "morePrecision".
85
139
  internalSlots.roundingType = 'morePrecision';
140
+ // 23.f. Set internalSlots.[[RoundingPriority]] to "morePrecision".
86
141
  internalSlots.roundingPriority = 'morePrecision';
87
142
  }
88
143
  else if (roundingPriority === 'morePrecision') {
144
+ // 24. Else if roundingPriority is "morePrecision", then
145
+ // 24.a. Set internalSlots.[[RoundingType]] to "morePrecision".
89
146
  internalSlots.roundingType = 'morePrecision';
147
+ // 24.b. Set internalSlots.[[RoundingPriority]] to "morePrecision".
90
148
  internalSlots.roundingPriority = 'morePrecision';
91
149
  }
92
150
  else if (roundingPriority === 'lessPrecision') {
151
+ // 25. Else if roundingPriority is "lessPrecision", then
152
+ // 25.a. Set internalSlots.[[RoundingType]] to "lessPrecision".
93
153
  internalSlots.roundingType = 'lessPrecision';
154
+ // 25.b. Set internalSlots.[[RoundingPriority]] to "lessPrecision".
94
155
  internalSlots.roundingPriority = 'lessPrecision';
95
156
  }
96
157
  else if (hasSd) {
158
+ // 26. Else if hasSd is true, then
159
+ // 26.a. Set internalSlots.[[RoundingType]] to "significantDigits".
97
160
  internalSlots.roundingType = 'significantDigits';
161
+ // 26.b. Set internalSlots.[[RoundingPriority]] to "auto".
98
162
  internalSlots.roundingPriority = 'auto';
99
163
  }
100
164
  else {
165
+ // 27. Else,
166
+ // 27.a. Set internalSlots.[[RoundingType]] to "fractionDigits".
101
167
  internalSlots.roundingType = 'fractionDigits';
168
+ // 27.b. Set internalSlots.[[RoundingPriority]] to "auto".
102
169
  internalSlots.roundingPriority = 'auto';
103
170
  }
171
+ // 28. If roundingIncrement is not 1, then
104
172
  if (roundingIncrement !== 1) {
105
- invariant(internalSlots.roundingType === 'fractionDigits', 'Invalid roundingType');
173
+ // 28.a. Assert: internalSlots.[[RoundingType]] is "fractionDigits".
174
+ invariant(internalSlots.roundingType === 'fractionDigits', 'Invalid roundingType', TypeError);
175
+ // 28.b. Assert: internalSlots.[[MaximumFractionDigits]] is equal to internalSlots.[[MinimumFractionDigits]].
106
176
  invariant(internalSlots.maximumFractionDigits ===
107
- internalSlots.minimumFractionDigits, 'With roundingIncrement > 1, maximumFractionDigits and minimumFractionDigits must be equal.');
177
+ internalSlots.minimumFractionDigits, 'With roundingIncrement > 1, maximumFractionDigits and minimumFractionDigits must be equal.', RangeError);
108
178
  }
109
179
  }
@@ -2,6 +2,4 @@ import { NumberFormatInternal, NumberFormatOptions } from '../types/number';
2
2
  /**
3
3
  * https://tc39.es/ecma402/#sec-setnumberformatunitoptions
4
4
  */
5
- export declare function SetNumberFormatUnitOptions(nf: Intl.NumberFormat, options: NumberFormatOptions | undefined, { getInternalSlots, }: {
6
- getInternalSlots(nf: Intl.NumberFormat): NumberFormatInternal;
7
- }): void;
5
+ export declare function SetNumberFormatUnitOptions(internalSlots: NumberFormatInternal, options?: NumberFormatOptions | undefined): void;
@@ -1,39 +1,50 @@
1
1
  import { GetOption } from '../GetOption';
2
2
  import { IsWellFormedCurrencyCode } from '../IsWellFormedCurrencyCode';
3
3
  import { IsWellFormedUnitIdentifier } from '../IsWellFormedUnitIdentifier';
4
+ import { invariant } from '../utils';
4
5
  /**
5
6
  * https://tc39.es/ecma402/#sec-setnumberformatunitoptions
6
7
  */
7
- export function SetNumberFormatUnitOptions(nf, options, _a) {
8
+ export function SetNumberFormatUnitOptions(internalSlots, options) {
8
9
  if (options === void 0) { options = Object.create(null); }
9
- var getInternalSlots = _a.getInternalSlots;
10
- var internalSlots = getInternalSlots(nf);
10
+ // 1. Let style be ? GetOption(options, "style", "string", « "decimal", "percent", "currency", "unit" », "decimal").
11
11
  var style = GetOption(options, 'style', 'string', ['decimal', 'percent', 'currency', 'unit'], 'decimal');
12
+ // 2. Set internalSlots.[[Style]] to style.
12
13
  internalSlots.style = style;
14
+ // 3. Let currency be ? GetOption(options, "currency", "string", undefined, undefined).
13
15
  var currency = GetOption(options, 'currency', 'string', undefined, undefined);
14
- if (currency !== undefined && !IsWellFormedCurrencyCode(currency)) {
15
- throw RangeError('Malformed currency code');
16
- }
17
- if (style === 'currency' && currency === undefined) {
18
- throw TypeError('currency cannot be undefined');
19
- }
16
+ // 4. If currency is not undefined, then
17
+ // a. If the result of IsWellFormedCurrencyCode(currency) is false, throw a RangeError exception.
18
+ invariant(currency === undefined || IsWellFormedCurrencyCode(currency), 'Malformed currency code', RangeError);
19
+ // 5. If style is "currency" and currency is undefined, throw a TypeError exception.
20
+ invariant(style !== 'currency' || currency !== undefined, 'currency cannot be undefined', TypeError);
21
+ // 6. Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol").
20
22
  var currencyDisplay = GetOption(options, 'currencyDisplay', 'string', ['code', 'symbol', 'narrowSymbol', 'name'], 'symbol');
23
+ // 7. Let currencySign be ? GetOption(options, "currencySign", "string", « "standard", "accounting" », "standard").
21
24
  var currencySign = GetOption(options, 'currencySign', 'string', ['standard', 'accounting'], 'standard');
25
+ // 8. Let unit be ? GetOption(options, "unit", "string", undefined, undefined).
22
26
  var unit = GetOption(options, 'unit', 'string', undefined, undefined);
23
- if (unit !== undefined && !IsWellFormedUnitIdentifier(unit)) {
24
- throw RangeError('Invalid unit argument for Intl.NumberFormat()');
25
- }
26
- if (style === 'unit' && unit === undefined) {
27
- throw TypeError('unit cannot be undefined');
28
- }
27
+ // 9. If unit is not undefined, then
28
+ // a. If the result of IsWellFormedUnitIdentifier(unit) is false, throw a RangeError exception.
29
+ invariant(unit === undefined || IsWellFormedUnitIdentifier(unit), 'Invalid unit argument for Intl.NumberFormat()', RangeError);
30
+ // 10. If style is "unit" and unit is undefined, throw a TypeError exception.
31
+ invariant(style !== 'unit' || unit !== undefined, 'unit cannot be undefined', TypeError);
32
+ // 11. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short").
29
33
  var unitDisplay = GetOption(options, 'unitDisplay', 'string', ['short', 'narrow', 'long'], 'short');
34
+ // 12. If style is "currency", then
30
35
  if (style === 'currency') {
36
+ // a. Set internalSlots.[[Currency]] to the result of converting currency to upper case as specified in 6.1.
31
37
  internalSlots.currency = currency.toUpperCase();
38
+ // b. Set internalSlots.[[CurrencyDisplay]] to currencyDisplay.
32
39
  internalSlots.currencyDisplay = currencyDisplay;
40
+ // c. Set internalSlots.[[CurrencySign]] to currencySign.
33
41
  internalSlots.currencySign = currencySign;
34
42
  }
43
+ // 13. If style is "unit", then
35
44
  if (style === 'unit') {
45
+ // a. Set internalSlots.[[Unit]] to unit.
36
46
  internalSlots.unit = unit;
47
+ // b. Set internalSlots.[[UnitDisplay]] to unitDisplay.
37
48
  internalSlots.unitDisplay = unitDisplay;
38
49
  }
39
50
  }
@@ -1,10 +1,9 @@
1
1
  import Decimal from 'decimal.js';
2
2
  import { RawNumberFormatResult, UnsignedRoundingModeType } from '../types/number';
3
3
  /**
4
- * TODO: dedup with intl-pluralrules and support BigInt
5
4
  * https://tc39.es/ecma402/#sec-torawfixed
6
5
  * @param x a finite non-negative Number or BigInt
7
- * @param minFraction and integer between 0 and 20
8
- * @param maxFraction and integer between 0 and 20
6
+ * @param minFraction an integer between 0 and 20
7
+ * @param maxFraction an integer between 0 and 20
9
8
  */
10
9
  export declare function ToRawFixed(x: Decimal, minFraction: number, maxFraction: number, roundingIncrement: number, unsignedRoundingMode: UnsignedRoundingModeType): RawNumberFormatResult;
@@ -1,15 +1,17 @@
1
1
  import Decimal from 'decimal.js';
2
- import { TEN } from '../constants';
3
2
  import { repeat } from '../utils';
4
3
  import { ApplyUnsignedRoundingMode } from './ApplyUnsignedRoundingMode';
4
+ //IMPL: Setting Decimal configuration
5
5
  Decimal.set({
6
6
  toExpPos: 100,
7
7
  });
8
+ //IMPL: Helper function to calculate raw fixed value
8
9
  function ToRawFixedFn(n, f) {
9
- return n.times(TEN.pow(-f));
10
+ return n.times(Decimal.pow(10, -f));
10
11
  }
12
+ //IMPL: Helper function to find n1 and r1
11
13
  function findN1R1(x, f, roundingIncrement) {
12
- var nx = x.times(TEN.pow(f)).floor();
14
+ var nx = x.times(Decimal.pow(10, f)).floor();
13
15
  var n1 = nx.div(roundingIncrement).floor().times(roundingIncrement);
14
16
  var r1 = ToRawFixedFn(n1, f);
15
17
  return {
@@ -17,8 +19,9 @@ function findN1R1(x, f, roundingIncrement) {
17
19
  r1: r1,
18
20
  };
19
21
  }
22
+ //IMPL: Helper function to find n2 and r2
20
23
  function findN2R2(x, f, roundingIncrement) {
21
- var nx = x.times(TEN.pow(f)).ceil();
24
+ var nx = x.times(Decimal.pow(10, f)).ceil();
22
25
  var n2 = nx.div(roundingIncrement).ceil().times(roundingIncrement);
23
26
  var r2 = ToRawFixedFn(n2, f);
24
27
  return {
@@ -27,57 +30,86 @@ function findN2R2(x, f, roundingIncrement) {
27
30
  };
28
31
  }
29
32
  /**
30
- * TODO: dedup with intl-pluralrules and support BigInt
31
33
  * https://tc39.es/ecma402/#sec-torawfixed
32
34
  * @param x a finite non-negative Number or BigInt
33
- * @param minFraction and integer between 0 and 20
34
- * @param maxFraction and integer between 0 and 20
35
+ * @param minFraction an integer between 0 and 20
36
+ * @param maxFraction an integer between 0 and 20
35
37
  */
36
38
  export function ToRawFixed(x, minFraction, maxFraction, roundingIncrement, unsignedRoundingMode) {
39
+ // 1. Let f be maxFraction.
37
40
  var f = maxFraction;
41
+ // 2. Let n1 and r1 be the results of performing the maximized rounding of x to f fraction digits.
38
42
  var _a = findN1R1(x, f, roundingIncrement), n1 = _a.n1, r1 = _a.r1;
43
+ // 3. Let n2 and r2 be the results of performing the minimized rounding of x to f fraction digits.
39
44
  var _b = findN2R2(x, f, roundingIncrement), n2 = _b.n2, r2 = _b.r2;
45
+ // 4. Let r be ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode).
40
46
  var r = ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode);
41
47
  var n, xFinal;
42
48
  var m;
49
+ // 5. If r is equal to r1, then
43
50
  if (r.eq(r1)) {
51
+ // a. Let n be n1.
44
52
  n = n1;
53
+ // b. Let xFinal be r1.
45
54
  xFinal = r1;
46
55
  }
47
56
  else {
57
+ // 6. Else,
58
+ // a. Let n be n2.
48
59
  n = n2;
60
+ // b. Let xFinal be r2.
49
61
  xFinal = r2;
50
62
  }
63
+ // 7. If n is 0, let m be "0".
51
64
  if (n.isZero()) {
52
65
  m = '0';
53
66
  }
54
67
  else {
68
+ // 8. Else, let m be the String representation of n.
55
69
  m = n.toString();
56
70
  }
57
71
  var int;
72
+ // 9. If f is not 0, then
58
73
  if (f !== 0) {
74
+ // a. Let k be the length of m.
59
75
  var k = m.length;
76
+ // b. If k < f, then
60
77
  if (k <= f) {
78
+ // i. Let z be the String value consisting of f + 1 - k occurrences of the character "0".
61
79
  var z = repeat('0', f - k + 1);
80
+ // ii. Set m to the string-concatenation of z and m.
62
81
  m = z + m;
82
+ // iii. Set k to f + 1.
63
83
  k = f + 1;
64
84
  }
85
+ // c. Let a be the substring of m from 0 to k - f.
65
86
  var a = m.slice(0, k - f);
87
+ // d. Let b be the substring of m from k - f to k.
66
88
  var b = m.slice(m.length - f);
89
+ // e. Set m to the string-concatenation of a, ".", and b.
67
90
  m = a + '.' + b;
91
+ // f. Let int be the length of a.
68
92
  int = a.length;
69
93
  }
70
94
  else {
95
+ // 10. Else, let int be the length of m.
71
96
  int = m.length;
72
97
  }
98
+ // 11. Let cut be maxFraction - minFraction.
73
99
  var cut = maxFraction - minFraction;
100
+ // 12. Repeat, while cut > 0 and the last character of m is "0",
74
101
  while (cut > 0 && m[m.length - 1] === '0') {
102
+ // a. Remove the last character from m.
75
103
  m = m.slice(0, m.length - 1);
104
+ // b. Decrease cut by 1.
76
105
  cut--;
77
106
  }
107
+ // 13. If the last character of m is ".", then
78
108
  if (m[m.length - 1] === '\u002e') {
109
+ // a. Remove the last character from m.
79
110
  m = m.slice(0, m.length - 1);
80
111
  }
112
+ // 14. Return the Record { [[FormattedString]]: m, [[RoundedNumber]]: xFinal, [[IntegerDigitsCount]]: int, [[RoundingMagnitude]]: -f }.
81
113
  return {
82
114
  formattedString: m,
83
115
  roundedNumber: xFinal,
@@ -1,3 +1,9 @@
1
1
  import Decimal from 'decimal.js';
2
2
  import { RawNumberFormatResult, UnsignedRoundingModeType } from '../types/number';
3
+ /**
4
+ * https://tc39.es/ecma402/#sec-torawprecision
5
+ * @param x a finite non-negative Number or BigInt
6
+ * @param minPrecision an integer between 1 and 21
7
+ * @param maxPrecision an integer between 1 and 21
8
+ */
3
9
  export declare function ToRawPrecision(x: Decimal, minPrecision: number, maxPrecision: number, unsignedRoundingMode: UnsignedRoundingModeType): RawNumberFormatResult;
@@ -1,23 +1,17 @@
1
1
  import Decimal from 'decimal.js';
2
- import { TEN, ZERO } from '../constants';
2
+ import { ZERO } from '../constants';
3
3
  import { invariant, repeat } from '../utils';
4
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
- }
5
+ //IMPL: Helper function to find n1, e1, and r1
13
6
  function findN1E1R1(x, p) {
14
- var maxN1 = TEN.pow(p);
15
- var minN1 = TEN.pow(p - 1);
7
+ var maxN1 = Decimal.pow(10, p);
8
+ var minN1 = Decimal.pow(10, p - 1);
16
9
  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();
10
+ var currentE1 = maxE1;
11
+ while (true) {
12
+ var currentN1 = x.div(Decimal.pow(10, currentE1.minus(p).plus(1))).floor();
19
13
  if (currentN1.lessThan(maxN1) && currentN1.greaterThanOrEqualTo(minN1)) {
20
- var currentR1 = ToRawPrecisionFn(currentN1, currentE1, p);
14
+ var currentR1 = currentN1.times(Decimal.pow(10, currentE1.minus(p).plus(1)));
21
15
  if (currentR1.lessThanOrEqualTo(x)) {
22
16
  return {
23
17
  n1: currentN1,
@@ -26,16 +20,19 @@ function findN1E1R1(x, p) {
26
20
  };
27
21
  }
28
22
  }
23
+ currentE1 = currentE1.minus(1);
29
24
  }
30
25
  }
26
+ //IMPL: Helper function to find n2, e2, and r2
31
27
  function findN2E2R2(x, p) {
32
- var maxN2 = TEN.pow(p);
33
- var minN2 = TEN.pow(p - 1);
28
+ var maxN2 = Decimal.pow(10, p);
29
+ var minN2 = Decimal.pow(10, p - 1);
34
30
  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();
31
+ var currentE2 = minE2;
32
+ while (true) {
33
+ var currentN2 = x.div(Decimal.pow(10, currentE2.minus(p).plus(1))).ceil();
37
34
  if (currentN2.lessThan(maxN2) && currentN2.greaterThanOrEqualTo(minN2)) {
38
- var currentR2 = ToRawPrecisionFn(currentN2, currentE2, p);
35
+ var currentR2 = currentN2.times(Decimal.pow(10, currentE2.minus(p).plus(1)));
39
36
  if (currentR2.greaterThanOrEqualTo(x)) {
40
37
  return {
41
38
  n2: currentN2,
@@ -44,59 +41,104 @@ function findN2E2R2(x, p) {
44
41
  };
45
42
  }
46
43
  }
44
+ currentE2 = currentE2.plus(1);
47
45
  }
48
46
  }
47
+ /**
48
+ * https://tc39.es/ecma402/#sec-torawprecision
49
+ * @param x a finite non-negative Number or BigInt
50
+ * @param minPrecision an integer between 1 and 21
51
+ * @param maxPrecision an integer between 1 and 21
52
+ */
49
53
  export function ToRawPrecision(x, minPrecision, maxPrecision, unsignedRoundingMode) {
54
+ // 1. Let p be maxPrecision.
50
55
  var p = maxPrecision;
51
56
  var m;
52
57
  var e;
53
58
  var xFinal;
59
+ // 2. If x = 0, then
54
60
  if (x.isZero()) {
61
+ // a. Let m be the String value consisting of p occurrences of the character "0".
55
62
  m = repeat('0', p);
63
+ // b. Let e be 0.
56
64
  e = 0;
65
+ // c. Let xFinal be 0.
57
66
  xFinal = ZERO;
58
67
  }
59
68
  else {
69
+ // 3. Else,
70
+ // a. Let {n1, e1, r1} be the result of findN1E1R1(x, p).
60
71
  var _a = findN1E1R1(x, p), n1 = _a.n1, e1 = _a.e1, r1 = _a.r1;
72
+ // b. Let {n2, e2, r2} be the result of findN2E2R2(x, p).
61
73
  var _b = findN2E2R2(x, p), n2 = _b.n2, e2 = _b.e2, r2 = _b.r2;
74
+ // c. Let r be ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode).
62
75
  var r = ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode);
63
- var n = void 0;
76
+ var n
77
+ // d. If r = r1, then
78
+ = void 0;
79
+ // d. If r = r1, then
64
80
  if (r.eq(r1)) {
81
+ // i. Let n be n1.
65
82
  n = n1;
83
+ // ii. Let e be e1.
66
84
  e = e1.toNumber();
85
+ // iii. Let xFinal be r1.
67
86
  xFinal = r1;
68
87
  }
69
88
  else {
89
+ // e. Else,
90
+ // i. Let n be n2.
70
91
  n = n2;
92
+ // ii. Let e be e2.
71
93
  e = e2.toNumber();
94
+ // iii. Let xFinal be r2.
72
95
  xFinal = r2;
73
96
  }
97
+ // f. Let m be the String representation of n.
74
98
  m = n.toString();
75
99
  }
76
100
  var int;
101
+ // 4. If e ≥ p - 1, then
77
102
  if (e >= p - 1) {
103
+ // a. Let m be the string-concatenation of m and p - 1 - e occurrences of the character "0".
78
104
  m = m + repeat('0', e - p + 1);
105
+ // b. Let int be e + 1.
79
106
  int = e + 1;
80
107
  }
81
108
  else if (e >= 0) {
109
+ // 5. Else if e ≥ 0, then
110
+ // a. Let m be the string-concatenation of the first e + 1 characters of m, ".", and the remaining p - (e + 1) characters of m.
82
111
  m = m.slice(0, e + 1) + '.' + m.slice(m.length - (p - (e + 1)));
112
+ // b. Let int be e + 1.
83
113
  int = e + 1;
84
114
  }
85
115
  else {
116
+ // 6. Else,
117
+ // a. Assert: e < 0.
86
118
  invariant(e < 0, 'e should be less than 0');
119
+ // b. Let m be the string-concatenation of "0.", -e - 1 occurrences of the character "0", and m.
87
120
  m = '0.' + repeat('0', -e - 1) + m;
121
+ // c. Let int be 1.
88
122
  int = 1;
89
123
  }
124
+ // 7. If m contains ".", and maxPrecision > minPrecision, then
90
125
  if (m.includes('.') && maxPrecision > minPrecision) {
126
+ // a. Let cut be maxPrecision - minPrecision.
91
127
  var cut = maxPrecision - minPrecision;
128
+ // b. Repeat, while cut > 0 and the last character of m is "0",
92
129
  while (cut > 0 && m[m.length - 1] === '0') {
130
+ // i. Remove the last character from m.
93
131
  m = m.slice(0, m.length - 1);
132
+ // ii. Decrease cut by 1.
94
133
  cut--;
95
134
  }
135
+ // c. If the last character of m is ".", then
96
136
  if (m[m.length - 1] === '.') {
137
+ // i. Remove the last character from m.
97
138
  m = m.slice(0, m.length - 1);
98
139
  }
99
140
  }
141
+ // 8. Return the Record { [[FormattedString]]: m, [[RoundedNumber]]: xFinal, [[IntegerDigitsCount]]: int, [[RoundingMagnitude]]: e }.
100
142
  return {
101
143
  formattedString: m,
102
144
  roundedNumber: xFinal,
@@ -1,5 +1,4 @@
1
1
  import Decimal from 'decimal.js';
2
- import { TEN } from '../constants';
3
2
  import { S_UNICODE_REGEX } from '../regex.generated';
4
3
  import { digitMapping } from './digit-mapping.generated';
5
4
  import { GetUnsignedRoundingMode } from './GetUnsignedRoundingMode';
@@ -164,7 +163,9 @@ export default function formatToParts(numberResult, data, pl, options) {
164
163
  var unitName = void 0;
165
164
  var currencyNameData = data.currencies[options.currency];
166
165
  if (currencyNameData) {
167
- unitName = selectPlural(pl, numberResult.roundedNumber.times(TEN.pow(exponent)).toNumber(), currencyNameData.displayName);
166
+ unitName = selectPlural(pl, numberResult.roundedNumber
167
+ .times(Decimal.pow(10, exponent))
168
+ .toNumber(), currencyNameData.displayName);
168
169
  }
169
170
  else {
170
171
  // Fallback for unknown currency
@@ -201,7 +202,9 @@ export default function formatToParts(numberResult, data, pl, options) {
201
202
  var unitPattern = void 0;
202
203
  if (unitData) {
203
204
  // Simple unit pattern
204
- unitPattern = selectPlural(pl, numberResult.roundedNumber.times(TEN.pow(exponent)).toNumber(), data.units.simple[unit][unitDisplay]);
205
+ unitPattern = selectPlural(pl, numberResult.roundedNumber
206
+ .times(Decimal.pow(10, exponent))
207
+ .toNumber(), data.units.simple[unit][unitDisplay]);
205
208
  }
206
209
  else {
207
210
  // See: http://unicode.org/reports/tr35/tr35-general.html#perUnitPatterns
@@ -209,7 +212,9 @@ export default function formatToParts(numberResult, data, pl, options) {
209
212
  // Implementation note: we are not following TR-35 here because we need to format to parts!
210
213
  var _c = unit.split('-per-'), numeratorUnit = _c[0], denominatorUnit = _c[1];
211
214
  unitData = data.units.simple[numeratorUnit];
212
- var numeratorUnitPattern = selectPlural(pl, numberResult.roundedNumber.times(TEN.pow(exponent)).toNumber(), data.units.simple[numeratorUnit][unitDisplay]);
215
+ var numeratorUnitPattern = selectPlural(pl, numberResult.roundedNumber
216
+ .times(Decimal.pow(10, exponent))
217
+ .toNumber(), data.units.simple[numeratorUnit][unitDisplay]);
213
218
  var perUnitPattern = data.units.simple[denominatorUnit].perUnit[unitDisplay];
214
219
  if (perUnitPattern) {
215
220
  // perUnitPattern exists, combine it with numeratorUnitPattern
@@ -0,0 +1,2 @@
1
+ import Decimal from 'decimal.js';
2
+ export declare function ToIntlMathematicalValue(input: unknown): Decimal;
@@ -0,0 +1,27 @@
1
+ import Decimal from 'decimal.js';
2
+ import { ToPrimitive } from './262';
3
+ export function ToIntlMathematicalValue(input) {
4
+ var primValue = ToPrimitive(input, 'number');
5
+ if (typeof primValue === 'bigint') {
6
+ return new Decimal(primValue);
7
+ }
8
+ // IMPL
9
+ if (primValue === undefined) {
10
+ return new Decimal(NaN);
11
+ }
12
+ if (primValue === true) {
13
+ return new Decimal(1);
14
+ }
15
+ if (primValue === false) {
16
+ return new Decimal(0);
17
+ }
18
+ if (primValue === null) {
19
+ return new Decimal(0);
20
+ }
21
+ try {
22
+ return new Decimal(primValue);
23
+ }
24
+ catch (e) {
25
+ return new Decimal(NaN);
26
+ }
27
+ }
package/lib/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export * from './NumberFormat/ComputeExponentForMagnitude';
16
16
  export * from './NumberFormat/CurrencyDigits';
17
17
  export { default as _formatToParts } from './NumberFormat/format_to_parts';
18
18
  export * from './NumberFormat/FormatApproximately';
19
+ export * from './NumberFormat/FormatNumeric';
19
20
  export * from './NumberFormat/FormatNumericRange';
20
21
  export * from './NumberFormat/FormatNumericRangeToParts';
21
22
  export * from './NumberFormat/FormatNumericToParts';
@@ -43,3 +44,4 @@ export * from './types/plural-rules';
43
44
  export * from './types/relative-time';
44
45
  export { createMemoizedDateTimeFormat, createMemoizedListFormat, createMemoizedLocale, createMemoizedNumberFormat, createMemoizedPluralRules, invariant, } from './utils';
45
46
  export { ZERO } from './constants';
47
+ export { ToIntlMathematicalValue } from './ToIntlMathematicalValue';