@fulcro/types 0.1.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.
Files changed (51) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +66 -0
  3. package/dist/bigInteger/index.d.ts +27 -0
  4. package/dist/bigInteger/index.js +76 -0
  5. package/dist/brand/index.d.ts +25 -0
  6. package/dist/brand/index.js +2 -0
  7. package/dist/decimal/arithmetic.d.ts +99 -0
  8. package/dist/decimal/arithmetic.js +388 -0
  9. package/dist/decimal/format.d.ts +55 -0
  10. package/dist/decimal/format.js +195 -0
  11. package/dist/decimal/index.d.ts +296 -0
  12. package/dist/decimal/index.js +407 -0
  13. package/dist/decimal/parse.d.ts +15 -0
  14. package/dist/decimal/parse.js +80 -0
  15. package/dist/decimal/parts.d.ts +83 -0
  16. package/dist/decimal/parts.js +103 -0
  17. package/dist/decimal/round.d.ts +32 -0
  18. package/dist/decimal/round.js +132 -0
  19. package/dist/doublePrecisionFloat/index.d.ts +19 -0
  20. package/dist/doublePrecisionFloat/index.js +12 -0
  21. package/dist/float/index.d.ts +25 -0
  22. package/dist/float/index.js +61 -0
  23. package/dist/halfPrecisionFloat/index.d.ts +20 -0
  24. package/dist/halfPrecisionFloat/index.js +63 -0
  25. package/dist/index.d.ts +22 -0
  26. package/dist/index.js +29 -0
  27. package/dist/integer/index.d.ts +163 -0
  28. package/dist/integer/index.js +402 -0
  29. package/dist/languageService/index.d.ts +21 -0
  30. package/dist/languageService/index.js +23 -0
  31. package/dist/layout/index.d.ts +33 -0
  32. package/dist/layout/index.js +2 -0
  33. package/dist/numericType/index.d.ts +174 -0
  34. package/dist/numericType/index.js +2 -0
  35. package/dist/roundingMode/index.d.ts +30 -0
  36. package/dist/roundingMode/index.js +29 -0
  37. package/dist/signedInteger/index.d.ts +40 -0
  38. package/dist/signedInteger/index.js +34 -0
  39. package/dist/singlePrecisionFloat/index.d.ts +20 -0
  40. package/dist/singlePrecisionFloat/index.js +15 -0
  41. package/dist/transformer/classify/index.d.ts +39 -0
  42. package/dist/transformer/classify/index.js +84 -0
  43. package/dist/transformer/index.d.ts +27 -0
  44. package/dist/transformer/index.js +30 -0
  45. package/dist/transformer/rewriter/index.d.ts +3 -0
  46. package/dist/transformer/rewriter/index.js +374 -0
  47. package/dist/unplugin/index.d.mts +15 -0
  48. package/dist/unplugin/index.mjs +31 -0
  49. package/dist/unsignedInteger/index.d.ts +36 -0
  50. package/dist/unsignedInteger/index.js +34 -0
  51. package/package.json +71 -0
@@ -0,0 +1,296 @@
1
+ import { type RoundingMode } from '../roundingMode/index.js';
2
+ /**
3
+ * A decimal floating point number with the semantics of IEEE 754 decimal128:
4
+ * thirty-four significant digits, exponents from -6143 to 6144, and the
5
+ * special values `NaN`, `Infinity`, `-Infinity` and `-0`.
6
+ *
7
+ * ```ts
8
+ * const price = Decimal.from('19.99');
9
+ *
10
+ * price.multiply(Decimal.from(3)).toString(); // '59.97'
11
+ * Decimal.from('0.1').add(Decimal.from('0.2')).equals(Decimal.from('0.3')); // true
12
+ * ```
13
+ *
14
+ * The semantics are those of the TC39 Decimal proposal, so that code written
15
+ * against this class reads the same against a native one:
16
+ *
17
+ * - **Trailing zeros are not observable.** `'1.20'` and `'1.2'` are the same
18
+ * value and print the same way.
19
+ * - **Every operation rounds once**, to thirty-four digits, half to even unless
20
+ * a mode is given. An exact result is never rounded.
21
+ * - **Operators refuse it.** `a + b`, `a < b` and `a == 1` throw a `TypeError`
22
+ * instead of coercing: an implicit conversion to `number` would lose exactly
23
+ * the digits the type exists to keep. Use the methods.
24
+ * - **Division by zero is not an error**, as in IEEE 754: it gives an infinity,
25
+ * and zero over zero gives `NaN`.
26
+ *
27
+ * Values are immutable. The layout is sixteen bytes aligned on sixteen, that of
28
+ * decimal128 — which is what `sizeOf<Decimal>()` reports, not what an instance
29
+ * costs in a JavaScript heap.
30
+ */
31
+ export declare class Decimal {
32
+ #private;
33
+ /** Layout of decimal128, declared for `sizeOf` and never assigned. */
34
+ readonly '~layout': {
35
+ readonly size: 16;
36
+ readonly alignment: 16;
37
+ };
38
+ /**
39
+ * Wraps parts that are already normalised. Private, because every value
40
+ * enters through {@link Decimal.from}, which is where it is checked.
41
+ *
42
+ * @param parts The value.
43
+ */
44
+ private constructor();
45
+ /**
46
+ * The largest finite decimal128 value: thirty-four nines, the last at
47
+ * 10^6111 — 9.999999999999999999999999999999999 × 10^6144.
48
+ */
49
+ static readonly maximum: Decimal;
50
+ /**
51
+ * The smallest finite value, the negation of {@link Decimal.maximum}. Not the
52
+ * smallest positive one, which is 1 × 10^-6176.
53
+ */
54
+ static readonly minimum: Decimal;
55
+ /**
56
+ * Converts a value into a decimal.
57
+ *
58
+ * - A **string** is parsed as a decimal literal — `'-12.5'`, `'1e-3'`,
59
+ * `'NaN'`, `'Infinity'` — and rounded half to even past thirty-four
60
+ * digits. Surrounding whitespace and hexadecimal are refused.
61
+ * - A **number** is converted from the shortest text that reads back as it,
62
+ * so `Decimal.from(0.1)` is exactly 0.1, not the binary value closest to
63
+ * it.
64
+ * - A **bigint** is converted exactly, then rounded if it has more than
65
+ * thirty-four digits.
66
+ * - A **Decimal** is returned as is.
67
+ *
68
+ * @param value Value to convert.
69
+ * @returns The decimal.
70
+ * @throws {SyntaxError} When a string is not a decimal literal.
71
+ * @throws {TypeError} When the value is of another kind.
72
+ */
73
+ static from: (value: Decimal | string | number | bigint) => Decimal;
74
+ /**
75
+ * Tells whether a value is a decimal.
76
+ *
77
+ * @param value Value to inspect.
78
+ * @returns `true` for an instance of this class.
79
+ */
80
+ static is: (value: unknown) => value is Decimal;
81
+ /**
82
+ * Adds a value.
83
+ *
84
+ * @param other Value to add.
85
+ * @param mode Rounding mode, half to even by default.
86
+ * @returns The sum.
87
+ */
88
+ add(other: Decimal, mode?: RoundingMode): Decimal;
89
+ /**
90
+ * Subtracts a value.
91
+ *
92
+ * @param other Value to subtract.
93
+ * @param mode Rounding mode, half to even by default.
94
+ * @returns The difference.
95
+ */
96
+ subtract(other: Decimal, mode?: RoundingMode): Decimal;
97
+ /**
98
+ * Multiplies by a value.
99
+ *
100
+ * @param other Value to multiply by.
101
+ * @param mode Rounding mode, half to even by default.
102
+ * @returns The product.
103
+ */
104
+ multiply(other: Decimal, mode?: RoundingMode): Decimal;
105
+ /**
106
+ * Divides by a value.
107
+ *
108
+ * @param other Divisor.
109
+ * @param mode Rounding mode, half to even by default.
110
+ * @returns The quotient; an infinity for a non-zero value over zero, and
111
+ * `NaN` for zero over zero.
112
+ */
113
+ divide(other: Decimal, mode?: RoundingMode): Decimal;
114
+ /**
115
+ * The remainder of a division truncated towards zero, with the sign of this
116
+ * value, as `%` computes it. Always exact.
117
+ *
118
+ * @param other Divisor.
119
+ * @returns The remainder; `NaN` for a zero divisor or an infinite dividend.
120
+ */
121
+ remainder(other: Decimal): Decimal;
122
+ /**
123
+ * Raises this value to an integer power, rounded once — the correctly
124
+ * rounded power whenever the exact one has up to 200,000 digits, which
125
+ * covers every base not within a hair of one.
126
+ *
127
+ * ```ts
128
+ * Decimal.from('1.1').power(Decimal.from(2)).toString(); // '1.21'
129
+ * Decimal.from('2').power(Decimal.from(-2)).toString(); // '0.25'
130
+ * ```
131
+ *
132
+ * Anything to the power zero is one, `NaN` included, as IEEE 754's `pown`
133
+ * has it.
134
+ *
135
+ * @param exponent Integer exponent, of any sign.
136
+ * @param mode Rounding mode, half to even by default.
137
+ * @returns The power.
138
+ * @throws {RangeError} When the exponent has a fractional part, or is not
139
+ * finite.
140
+ */
141
+ power(exponent: Decimal, mode?: RoundingMode): Decimal;
142
+ /**
143
+ * The value with its sign flipped.
144
+ *
145
+ * @returns The negated value.
146
+ */
147
+ negate(): Decimal;
148
+ /**
149
+ * The value without its sign.
150
+ *
151
+ * @returns The absolute value.
152
+ */
153
+ absolute(): Decimal;
154
+ /**
155
+ * Rounds to a number of places after the point.
156
+ *
157
+ * ```ts
158
+ * Decimal.from('2.345').round(2).toString(); // '2.34', half to even
159
+ * Decimal.from('2.345').round(2, 'halfAwayFromZero').toString(); // '2.35'
160
+ * Decimal.from('1250').round(-2).toString(); // '1200'
161
+ * ```
162
+ *
163
+ * @param places Places after the point, zero by default; negative rounds to
164
+ * tens, hundreds and so on.
165
+ * @param mode Rounding mode, half to even by default.
166
+ * @returns The rounded value.
167
+ * @throws {RangeError} When `places` is not an integer.
168
+ */
169
+ round(places?: number, mode?: RoundingMode): Decimal;
170
+ /**
171
+ * Compares with a value.
172
+ *
173
+ * @param other Value to compare with.
174
+ * @returns -1 when this value is smaller, 1 when it is larger, 0 when they
175
+ * are equal — `0` and `-0` included — and `undefined` when either is `NaN`.
176
+ */
177
+ compare(other: Decimal): -1 | 0 | 1 | undefined;
178
+ /**
179
+ * Tells whether two values are equal. `NaN` equals nothing, itself
180
+ * included; `0` equals `-0`.
181
+ *
182
+ * @param other Value to compare with.
183
+ * @returns `true` when they are equal.
184
+ */
185
+ equals(other: Decimal): boolean;
186
+ /**
187
+ * @param other Value to compare with.
188
+ * @returns `true` when this value is smaller; `false` when either is `NaN`.
189
+ */
190
+ lessThan(other: Decimal): boolean;
191
+ /**
192
+ * @param other Value to compare with.
193
+ * @returns `true` when this value is smaller or equal; `false` when either
194
+ * is `NaN`.
195
+ */
196
+ lessThanOrEqual(other: Decimal): boolean;
197
+ /**
198
+ * @param other Value to compare with.
199
+ * @returns `true` when this value is larger; `false` when either is `NaN`.
200
+ */
201
+ greaterThan(other: Decimal): boolean;
202
+ /**
203
+ * @param other Value to compare with.
204
+ * @returns `true` when this value is larger or equal; `false` when either
205
+ * is `NaN`.
206
+ */
207
+ greaterThanOrEqual(other: Decimal): boolean;
208
+ /** @returns `true` when the value is `NaN`. */
209
+ isNaN(): boolean;
210
+ /** @returns `true` when the value is neither an infinity nor `NaN`. */
211
+ isFinite(): boolean;
212
+ /** @returns `true` for `0` and `-0`. */
213
+ isZero(): boolean;
214
+ /**
215
+ * Reads the sign bit, which is set for `-0` and `-Infinity` as well as for
216
+ * negative values — the one way to tell `-0` from `0`.
217
+ *
218
+ * @returns `true` when the sign bit is set; `false` for `NaN`.
219
+ */
220
+ isNegative(): boolean;
221
+ /**
222
+ * The shortest text that reads back as this value, in plain notation from
223
+ * 10^-6 to 10^21 and exponential outside it, as `Number` prints.
224
+ *
225
+ * @returns The text.
226
+ */
227
+ toString(): string;
228
+ /**
229
+ * The value with a fixed number of digits after the point, in plain
230
+ * notation.
231
+ *
232
+ * @param fractionDigits Digits after the point, from 0 to 100; 0 by default.
233
+ * @param mode Rounding mode, half to even by default.
234
+ * @returns The text.
235
+ * @throws {RangeError} When `fractionDigits` is out of range.
236
+ */
237
+ toFixed(fractionDigits?: number, mode?: RoundingMode): string;
238
+ /**
239
+ * The value with a number of significant digits.
240
+ *
241
+ * @param precision Significant digits, from 1 to 100.
242
+ * @param mode Rounding mode, half to even by default.
243
+ * @returns The text, exponential when the exponent is below -6 or at least
244
+ * the precision, as `Number.prototype.toPrecision` does.
245
+ * @throws {RangeError} When `precision` is out of range.
246
+ */
247
+ toPrecision(precision: number, mode?: RoundingMode): string;
248
+ /**
249
+ * The value in exponential notation.
250
+ *
251
+ * @param fractionDigits Digits after the point, from 0 to 100, or as many
252
+ * as the value has when omitted.
253
+ * @param mode Rounding mode, half to even by default.
254
+ * @returns The text.
255
+ * @throws {RangeError} When `fractionDigits` is out of range.
256
+ */
257
+ toExponential(fractionDigits?: number, mode?: RoundingMode): string;
258
+ /**
259
+ * The value formatted for a locale, by `Intl.NumberFormat`, which formats
260
+ * the decimal text itself rather than a `number` converted from it — so no
261
+ * digit is lost on the way.
262
+ *
263
+ * @param locales Locale or locales, as `Intl.NumberFormat` takes them.
264
+ * @param options Formatting options, as `Intl.NumberFormat` takes them.
265
+ * @returns The formatted text.
266
+ */
267
+ toLocaleString(locales?: Intl.LocalesArgument, options?: Intl.NumberFormatOptions): string;
268
+ /**
269
+ * The text of the value, so that `JSON.stringify` writes it as a string
270
+ * rather than as `{}`, and without the digits a JSON number would lose.
271
+ *
272
+ * @returns The same text as {@link Decimal.toString}.
273
+ */
274
+ toJSON(): string;
275
+ /**
276
+ * The nearest `number`, rounded once, from the decimal text.
277
+ *
278
+ * @returns The number; `NaN` and the infinities convert to their own.
279
+ */
280
+ toNumber(): number;
281
+ /**
282
+ * The value as a `bigint`, exactly.
283
+ *
284
+ * @returns The integer.
285
+ * @throws {RangeError} When the value has a fractional part, or is not
286
+ * finite.
287
+ */
288
+ toBigInt(): bigint;
289
+ /**
290
+ * Refuses the implicit conversion every operator performs.
291
+ *
292
+ * @returns Never.
293
+ * @throws {TypeError} Always.
294
+ */
295
+ valueOf(): never;
296
+ }
@@ -0,0 +1,407 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Decimal = void 0;
4
+ const roundingMode_1 = require("../roundingMode/index.js");
5
+ const arithmetic_1 = require("./arithmetic");
6
+ const format_1 = require("./format");
7
+ const parse_1 = require("./parse");
8
+ const parts_1 = require("./parts");
9
+ /** Rounding applied wherever a mode is optional. */
10
+ const DEFAULT_MODE = 'halfEven';
11
+ /**
12
+ * A decimal floating point number with the semantics of IEEE 754 decimal128:
13
+ * thirty-four significant digits, exponents from -6143 to 6144, and the
14
+ * special values `NaN`, `Infinity`, `-Infinity` and `-0`.
15
+ *
16
+ * ```ts
17
+ * const price = Decimal.from('19.99');
18
+ *
19
+ * price.multiply(Decimal.from(3)).toString(); // '59.97'
20
+ * Decimal.from('0.1').add(Decimal.from('0.2')).equals(Decimal.from('0.3')); // true
21
+ * ```
22
+ *
23
+ * The semantics are those of the TC39 Decimal proposal, so that code written
24
+ * against this class reads the same against a native one:
25
+ *
26
+ * - **Trailing zeros are not observable.** `'1.20'` and `'1.2'` are the same
27
+ * value and print the same way.
28
+ * - **Every operation rounds once**, to thirty-four digits, half to even unless
29
+ * a mode is given. An exact result is never rounded.
30
+ * - **Operators refuse it.** `a + b`, `a < b` and `a == 1` throw a `TypeError`
31
+ * instead of coercing: an implicit conversion to `number` would lose exactly
32
+ * the digits the type exists to keep. Use the methods.
33
+ * - **Division by zero is not an error**, as in IEEE 754: it gives an infinity,
34
+ * and zero over zero gives `NaN`.
35
+ *
36
+ * Values are immutable. The layout is sixteen bytes aligned on sixteen, that of
37
+ * decimal128 — which is what `sizeOf<Decimal>()` reports, not what an instance
38
+ * costs in a JavaScript heap.
39
+ */
40
+ class Decimal {
41
+ /** The value, taken apart and normalised. */
42
+ #parts;
43
+ /**
44
+ * Wraps parts that are already normalised. Private, because every value
45
+ * enters through {@link Decimal.from}, which is where it is checked.
46
+ *
47
+ * @param parts The value.
48
+ */
49
+ constructor(parts) {
50
+ this.#parts = parts;
51
+ }
52
+ /**
53
+ * The largest finite decimal128 value: thirty-four nines, the last at
54
+ * 10^6111 — 9.999999999999999999999999999999999 × 10^6144.
55
+ */
56
+ static maximum = new Decimal({
57
+ kind: 'finite',
58
+ negative: false,
59
+ coefficient: (0, parts_1.powerOfTen)(parts_1.PRECISION) - 1n,
60
+ exponent: parts_1.MAXIMUM_ADJUSTED_EXPONENT - parts_1.PRECISION + 1,
61
+ });
62
+ /**
63
+ * The smallest finite value, the negation of {@link Decimal.maximum}. Not the
64
+ * smallest positive one, which is 1 × 10^-6176.
65
+ */
66
+ static minimum = Decimal.maximum.negate();
67
+ /**
68
+ * Converts a value into a decimal.
69
+ *
70
+ * - A **string** is parsed as a decimal literal — `'-12.5'`, `'1e-3'`,
71
+ * `'NaN'`, `'Infinity'` — and rounded half to even past thirty-four
72
+ * digits. Surrounding whitespace and hexadecimal are refused.
73
+ * - A **number** is converted from the shortest text that reads back as it,
74
+ * so `Decimal.from(0.1)` is exactly 0.1, not the binary value closest to
75
+ * it.
76
+ * - A **bigint** is converted exactly, then rounded if it has more than
77
+ * thirty-four digits.
78
+ * - A **Decimal** is returned as is.
79
+ *
80
+ * @param value Value to convert.
81
+ * @returns The decimal.
82
+ * @throws {SyntaxError} When a string is not a decimal literal.
83
+ * @throws {TypeError} When the value is of another kind.
84
+ */
85
+ static from = (value) => {
86
+ if (value instanceof Decimal)
87
+ return value;
88
+ if (typeof value === 'string')
89
+ return new Decimal((0, parse_1.parseDecimal)(value));
90
+ if (typeof value === 'bigint') {
91
+ return new Decimal((0, parse_1.parseDecimal)(value.toString()));
92
+ }
93
+ if (typeof value === 'number') {
94
+ if (Number.isNaN(value))
95
+ return new Decimal(parts_1.NOT_A_NUMBER);
96
+ if (value === Infinity || value === -Infinity) {
97
+ return new Decimal((0, parts_1.infinity)(value < 0));
98
+ }
99
+ // `String(-0)` is `'0'`, which would lose the sign.
100
+ if (value === 0)
101
+ return new Decimal((0, parts_1.zero)(Object.is(value, -0)));
102
+ return new Decimal((0, parse_1.parseDecimal)(String(value)));
103
+ }
104
+ throw new TypeError(`Decimal.from: expected a Decimal, a string, a number or a bigint, received ${typeof value}.`);
105
+ };
106
+ /**
107
+ * Tells whether a value is a decimal.
108
+ *
109
+ * @param value Value to inspect.
110
+ * @returns `true` for an instance of this class.
111
+ */
112
+ static is = (value) => value instanceof Decimal;
113
+ /**
114
+ * Adds a value.
115
+ *
116
+ * @param other Value to add.
117
+ * @param mode Rounding mode, half to even by default.
118
+ * @returns The sum.
119
+ */
120
+ add(other, mode = DEFAULT_MODE) {
121
+ return new Decimal((0, arithmetic_1.addParts)(this.#parts, other.#parts, (0, roundingMode_1.requireRoundingMode)('Decimal.add', mode)));
122
+ }
123
+ /**
124
+ * Subtracts a value.
125
+ *
126
+ * @param other Value to subtract.
127
+ * @param mode Rounding mode, half to even by default.
128
+ * @returns The difference.
129
+ */
130
+ subtract(other, mode = DEFAULT_MODE) {
131
+ return new Decimal((0, arithmetic_1.addParts)(this.#parts, other.negate().#parts, (0, roundingMode_1.requireRoundingMode)('Decimal.subtract', mode)));
132
+ }
133
+ /**
134
+ * Multiplies by a value.
135
+ *
136
+ * @param other Value to multiply by.
137
+ * @param mode Rounding mode, half to even by default.
138
+ * @returns The product.
139
+ */
140
+ multiply(other, mode = DEFAULT_MODE) {
141
+ return new Decimal((0, arithmetic_1.multiplyParts)(this.#parts, other.#parts, (0, roundingMode_1.requireRoundingMode)('Decimal.multiply', mode)));
142
+ }
143
+ /**
144
+ * Divides by a value.
145
+ *
146
+ * @param other Divisor.
147
+ * @param mode Rounding mode, half to even by default.
148
+ * @returns The quotient; an infinity for a non-zero value over zero, and
149
+ * `NaN` for zero over zero.
150
+ */
151
+ divide(other, mode = DEFAULT_MODE) {
152
+ return new Decimal((0, arithmetic_1.divideParts)(this.#parts, other.#parts, (0, roundingMode_1.requireRoundingMode)('Decimal.divide', mode)));
153
+ }
154
+ /**
155
+ * The remainder of a division truncated towards zero, with the sign of this
156
+ * value, as `%` computes it. Always exact.
157
+ *
158
+ * @param other Divisor.
159
+ * @returns The remainder; `NaN` for a zero divisor or an infinite dividend.
160
+ */
161
+ remainder(other) {
162
+ return new Decimal((0, arithmetic_1.remainderParts)(this.#parts, other.#parts));
163
+ }
164
+ /**
165
+ * Raises this value to an integer power, rounded once — the correctly
166
+ * rounded power whenever the exact one has up to 200,000 digits, which
167
+ * covers every base not within a hair of one.
168
+ *
169
+ * ```ts
170
+ * Decimal.from('1.1').power(Decimal.from(2)).toString(); // '1.21'
171
+ * Decimal.from('2').power(Decimal.from(-2)).toString(); // '0.25'
172
+ * ```
173
+ *
174
+ * Anything to the power zero is one, `NaN` included, as IEEE 754's `pown`
175
+ * has it.
176
+ *
177
+ * @param exponent Integer exponent, of any sign.
178
+ * @param mode Rounding mode, half to even by default.
179
+ * @returns The power.
180
+ * @throws {RangeError} When the exponent has a fractional part, or is not
181
+ * finite.
182
+ */
183
+ power(exponent, mode = DEFAULT_MODE) {
184
+ const { kind, negative, coefficient, exponent: scale } = exponent.#parts;
185
+ if (kind !== 'finite' || scale < 0) {
186
+ throw new RangeError(`Decimal.power: expected an integer exponent, received ${exponent.toString()}.`);
187
+ }
188
+ const power = (negative ? -coefficient : coefficient) * (0, parts_1.powerOfTen)(scale);
189
+ return new Decimal((0, arithmetic_1.powerParts)(this.#parts, power, (0, roundingMode_1.requireRoundingMode)('Decimal.power', mode)));
190
+ }
191
+ /**
192
+ * The value with its sign flipped.
193
+ *
194
+ * @returns The negated value.
195
+ */
196
+ negate() {
197
+ if (this.#parts.kind === 'nan')
198
+ return this;
199
+ return new Decimal({ ...this.#parts, negative: !this.#parts.negative });
200
+ }
201
+ /**
202
+ * The value without its sign.
203
+ *
204
+ * @returns The absolute value.
205
+ */
206
+ absolute() {
207
+ if (!this.#parts.negative)
208
+ return this;
209
+ return new Decimal({ ...this.#parts, negative: false });
210
+ }
211
+ /**
212
+ * Rounds to a number of places after the point.
213
+ *
214
+ * ```ts
215
+ * Decimal.from('2.345').round(2).toString(); // '2.34', half to even
216
+ * Decimal.from('2.345').round(2, 'halfAwayFromZero').toString(); // '2.35'
217
+ * Decimal.from('1250').round(-2).toString(); // '1200'
218
+ * ```
219
+ *
220
+ * @param places Places after the point, zero by default; negative rounds to
221
+ * tens, hundreds and so on.
222
+ * @param mode Rounding mode, half to even by default.
223
+ * @returns The rounded value.
224
+ * @throws {RangeError} When `places` is not an integer.
225
+ */
226
+ round(places = 0, mode = DEFAULT_MODE) {
227
+ if (!Number.isSafeInteger(places)) {
228
+ throw new RangeError(`Decimal.round: expected an integer number of places, received ${places}.`);
229
+ }
230
+ return new Decimal((0, arithmetic_1.roundParts)(this.#parts, places, (0, roundingMode_1.requireRoundingMode)('Decimal.round', mode)));
231
+ }
232
+ /**
233
+ * Compares with a value.
234
+ *
235
+ * @param other Value to compare with.
236
+ * @returns -1 when this value is smaller, 1 when it is larger, 0 when they
237
+ * are equal — `0` and `-0` included — and `undefined` when either is `NaN`.
238
+ */
239
+ compare(other) {
240
+ return (0, arithmetic_1.compareParts)(this.#parts, other.#parts);
241
+ }
242
+ /**
243
+ * Tells whether two values are equal. `NaN` equals nothing, itself
244
+ * included; `0` equals `-0`.
245
+ *
246
+ * @param other Value to compare with.
247
+ * @returns `true` when they are equal.
248
+ */
249
+ equals(other) {
250
+ return this.compare(other) === 0;
251
+ }
252
+ /**
253
+ * @param other Value to compare with.
254
+ * @returns `true` when this value is smaller; `false` when either is `NaN`.
255
+ */
256
+ lessThan(other) {
257
+ return this.compare(other) === -1;
258
+ }
259
+ /**
260
+ * @param other Value to compare with.
261
+ * @returns `true` when this value is smaller or equal; `false` when either
262
+ * is `NaN`.
263
+ */
264
+ lessThanOrEqual(other) {
265
+ const order = this.compare(other);
266
+ return order === -1 || order === 0;
267
+ }
268
+ /**
269
+ * @param other Value to compare with.
270
+ * @returns `true` when this value is larger; `false` when either is `NaN`.
271
+ */
272
+ greaterThan(other) {
273
+ return this.compare(other) === 1;
274
+ }
275
+ /**
276
+ * @param other Value to compare with.
277
+ * @returns `true` when this value is larger or equal; `false` when either
278
+ * is `NaN`.
279
+ */
280
+ greaterThanOrEqual(other) {
281
+ const order = this.compare(other);
282
+ return order === 1 || order === 0;
283
+ }
284
+ /** @returns `true` when the value is `NaN`. */
285
+ isNaN() {
286
+ return this.#parts.kind === 'nan';
287
+ }
288
+ /** @returns `true` when the value is neither an infinity nor `NaN`. */
289
+ isFinite() {
290
+ return this.#parts.kind === 'finite';
291
+ }
292
+ /** @returns `true` for `0` and `-0`. */
293
+ isZero() {
294
+ return (0, parts_1.isZero)(this.#parts);
295
+ }
296
+ /**
297
+ * Reads the sign bit, which is set for `-0` and `-Infinity` as well as for
298
+ * negative values — the one way to tell `-0` from `0`.
299
+ *
300
+ * @returns `true` when the sign bit is set; `false` for `NaN`.
301
+ */
302
+ isNegative() {
303
+ return this.#parts.negative;
304
+ }
305
+ /**
306
+ * The shortest text that reads back as this value, in plain notation from
307
+ * 10^-6 to 10^21 and exponential outside it, as `Number` prints.
308
+ *
309
+ * @returns The text.
310
+ */
311
+ toString() {
312
+ return (0, format_1.formatDecimal)(this.#parts);
313
+ }
314
+ /**
315
+ * The value with a fixed number of digits after the point, in plain
316
+ * notation.
317
+ *
318
+ * @param fractionDigits Digits after the point, from 0 to 100; 0 by default.
319
+ * @param mode Rounding mode, half to even by default.
320
+ * @returns The text.
321
+ * @throws {RangeError} When `fractionDigits` is out of range.
322
+ */
323
+ toFixed(fractionDigits = 0, mode = DEFAULT_MODE) {
324
+ return (0, format_1.formatFixed)(this.#parts, (0, format_1.requireDigits)('toFixed', fractionDigits, 0), (0, roundingMode_1.requireRoundingMode)('Decimal.toFixed', mode));
325
+ }
326
+ /**
327
+ * The value with a number of significant digits.
328
+ *
329
+ * @param precision Significant digits, from 1 to 100.
330
+ * @param mode Rounding mode, half to even by default.
331
+ * @returns The text, exponential when the exponent is below -6 or at least
332
+ * the precision, as `Number.prototype.toPrecision` does.
333
+ * @throws {RangeError} When `precision` is out of range.
334
+ */
335
+ toPrecision(precision, mode = DEFAULT_MODE) {
336
+ return (0, format_1.formatPrecision)(this.#parts, (0, format_1.requireDigits)('toPrecision', precision, 1), (0, roundingMode_1.requireRoundingMode)('Decimal.toPrecision', mode));
337
+ }
338
+ /**
339
+ * The value in exponential notation.
340
+ *
341
+ * @param fractionDigits Digits after the point, from 0 to 100, or as many
342
+ * as the value has when omitted.
343
+ * @param mode Rounding mode, half to even by default.
344
+ * @returns The text.
345
+ * @throws {RangeError} When `fractionDigits` is out of range.
346
+ */
347
+ toExponential(fractionDigits, mode = DEFAULT_MODE) {
348
+ return (0, format_1.formatExponential)(this.#parts, fractionDigits === undefined
349
+ ? undefined
350
+ : (0, format_1.requireDigits)('toExponential', fractionDigits, 0), (0, roundingMode_1.requireRoundingMode)('Decimal.toExponential', mode));
351
+ }
352
+ /**
353
+ * The value formatted for a locale, by `Intl.NumberFormat`, which formats
354
+ * the decimal text itself rather than a `number` converted from it — so no
355
+ * digit is lost on the way.
356
+ *
357
+ * @param locales Locale or locales, as `Intl.NumberFormat` takes them.
358
+ * @param options Formatting options, as `Intl.NumberFormat` takes them.
359
+ * @returns The formatted text.
360
+ */
361
+ toLocaleString(locales, options) {
362
+ return new Intl.NumberFormat(locales, options).format(this.toString());
363
+ }
364
+ /**
365
+ * The text of the value, so that `JSON.stringify` writes it as a string
366
+ * rather than as `{}`, and without the digits a JSON number would lose.
367
+ *
368
+ * @returns The same text as {@link Decimal.toString}.
369
+ */
370
+ toJSON() {
371
+ return this.toString();
372
+ }
373
+ /**
374
+ * The nearest `number`, rounded once, from the decimal text.
375
+ *
376
+ * @returns The number; `NaN` and the infinities convert to their own.
377
+ */
378
+ toNumber() {
379
+ return Number(this.toString());
380
+ }
381
+ /**
382
+ * The value as a `bigint`, exactly.
383
+ *
384
+ * @returns The integer.
385
+ * @throws {RangeError} When the value has a fractional part, or is not
386
+ * finite.
387
+ */
388
+ toBigInt() {
389
+ const { kind, negative, coefficient, exponent } = this.#parts;
390
+ if (kind !== 'finite' || exponent < 0) {
391
+ throw new RangeError(`Decimal.toBigInt: expected an integer, received ${this.toString()}.`);
392
+ }
393
+ const magnitude = coefficient * (0, parts_1.powerOfTen)(exponent);
394
+ return negative ? -magnitude : magnitude;
395
+ }
396
+ /**
397
+ * Refuses the implicit conversion every operator performs.
398
+ *
399
+ * @returns Never.
400
+ * @throws {TypeError} Always.
401
+ */
402
+ valueOf() {
403
+ throw new TypeError('Decimal cannot be converted to a primitive implicitly: operators such as + and < would lose its digits. ' +
404
+ 'Use add(), compare() or toString() instead.');
405
+ }
406
+ }
407
+ exports.Decimal = Decimal;