• Toggle shortcuts help`?`
• Toggle "can call user code" annotations`u`
• Jump to search box`/`
• Toggle pinning of the current clause`p`
• Jump to nth pin`1-9`

# Introduction

This specification consists of two parts:

• The specification of the Decimal proposal and everything related to it, proposed to be added to ECMA-262 in new sections;
• A list of amendments to be made to ECMA-402.

# Introduction

Decimal128 values, as specified here, are intended to represent base-10 (decimal) numbers as specified in IEEE 754 Decimal128. A Decimal128 value, as specified here, is one of the following four kinds of values:

• NaN𝔻, represending a decimal not-a-number
• +∞𝔻, representing positive infinity as a decimal,
• -∞𝔻, representing negative infinity as a decimal,
• « v, q »𝔻, where v and q satisfy the following conditions:
Note 1

A Decimal128 value is not an ECMAScript language value.

A Decimal128 value is said to be finite if it has the form « v, q »𝔻. A zero Decimal128 value is a finite Decimal128 value of the form « 0𝔻, q »𝔻 or « −0𝔻, q »𝔻. A finite non-zero Decimal128 value is one of the form « v, q »𝔻 where v is a mathematical value.

The mathematical value of a finite Decimal128 value x = « v, q »𝔻 is defined as follows:

Decimal128 values defined in this section are ECMAScript analogues of IEEE 754 Decimal128 values. The full spectrum of values defined by Decimal128 are available here, though there is only one Decimal128 value, NaN𝔻, representing all possible IEEE 754 Decimal128 NaN values.

A Decimal128 rounding mode is one of the String values "ceil", "floor", "trunc", "halfExpand", and "halfEven". The default rounding mode is the String value "halfEven".

For every finite Decimal128 value x = « v, q »𝔻, we define:

• cohort(x) is v;
• quantum(x) is q.

For every non-NaN Decimal128 value, we define its sign as follows:

• sign(+∞𝔻) = 1
• sign(-∞𝔻) = -1
• sign+0𝔻, q ») = 1
• sign−0𝔻, q ») = -1
• signv, q ») = v / abs(v)

For every finite non-zero Decimal128 value « v, q »𝔻 there exists a unique integer e and mathematical value s such that

1. v = s × 10e
2. 1 ≤ abs(s) < 10

We call e the exponent and s the significand of « v, q »𝔻. The exponent and significand are undefined for NaN, non-finite, and zero Decimal128 values.

Note 3

The significand of a finite non-zero Decimal128 value is a rational number.

Note 4

The exponent e of finite non-zero Decimal128 values is an integer satisfying 6144 ≥ e ≥ -6176.

A finite non-zero Decimal128 value is normalized if its exponent e satisfies 6144 ≥ e ≥ -6143. A finite non-zero Decimal128 value is denormalized if its exponent e satisfies -6144 ≥ e ≥ -6176.

A decimal cohort is one of the values NaN𝔻, +∞𝔻, -∞𝔻, +0𝔻, −0𝔻, or a mathematical value.

For a proper discussion of rounding, we need to separate how rounding occurs with normalized compared with denormlized values. For a normalized Decimal128 value we define its truncated exponent as equal to its exponent. For zero or denormalized Decimal128 values we define the truncated exponent as the constant -6143. Given this, we define the scaled significand of a finite Decimal128 value as follows:

• The scaled significand of a zero Decimal128 value is 0
• The scaled significand of a non-zero Decimal128 value _x = « v, q »𝔻 is v × 1033 − te, where te is the truncated exponent of x.
Note 5

The scaled significand of a finite Decimal128 value is always an integer whose absolute value is less than 1034.

# 1.1.1 RoundToDecimal128Domain ( v [ , roundingMode ] )

The abstract operation RoundToDecimal128Domain takes argument v (a mathematical value) and optional argument roundingMode (a Decimal128 rounding mode) and returns +∞𝔻, -∞𝔻, +0𝔻, −0𝔻, or a mathematical value. It computes the closest approximation to a given mathematical value, rounded according to the given rounding mode, that is available within the limits of Decimal128. It performs the following steps when called:

1. If v = 0, return +0𝔻.
2. If v < 0, then
1. Let reverseRoundingMode be roundingMode.
2. If roundingMode is "floor", set reverseRoundingMode to "ceil".
3. If roundingMode is "ceil", set reverseRoundingMode to "floor".
4. Let d be RoundToDecimal128Domain(–v, reverseRoundingMode).
5. If d is +∞𝔻, return –∞𝔻.
6. If d is +0𝔻, return −0𝔻.
7. Assert: d is a mathematical value.
8. Return –d.
3. Let e be the unique integer such that 10ev < 10e+1.
4. Let te be e − 33.
5. If te < –6176, set te to –6176.
6. Let m be v × 10te.
7. Let rounded be ApplyRoundingModeToPositive(m, roundingMode).
8. If rounded = 1034, then
1. Set te to te + 1.
2. Set rounded = to 1033.
9. If te > 6111, return +∞𝔻.
10. If rounded = 0, return +0𝔻.
11. Return rounded × 10te.

# 1.1.1.1 ApplyRoundingModeToPositive ( m, roundingMode )

The abstract operation ApplyRoundingModeToPositive takes arguments m (a positive mathematical value) and roundingMode (a Decimal128 rounding mode) and returns +∞𝔻, +0𝔻, or a mathematical value. It computes the closest approximation to a given mathematical value,which must be positive, rounded according to the given rounding mode, that is available within the limits of Decimal128. It performs the following steps when called:

1. Let mLow be floor(m).
2. Let fraction be mmLow.
3. If fraction = 0, return mLow.
4. Let mHigh be mLow + 1.
5. If roundingMode is "floor" or "trunc", return mLow.
6. If roundingMode is "ceil", return mHigh.
7. If fraction < 0.5, return mLow.
8. If fraction > 0.5, return mHigh.
9. If roundingMode is "halfExpand", return mHigh.
10. If mLow is an even integer, return mLow.
11. Return mHigh.

# 1.1.2 PickQuantum ( d, v, preferredQuantum )

The abstract operation PickQuantum takes arguments d (a decimal cohort), v (a mathematical value), and preferredQuantum (an integer) and returns a Decimal128 value. It takes a decimal cohort, a mathematical value, and an integer and produces a Decimal128 value in the cohort of d. If d is an exact Decimal128 cohort representation of v, PickQuantum picks the quantum as close as possible to qPreferred; if d is not an exact Decimal128 cohort representation of v, PickQuantum picks the lowest possible quantum. It performs the following steps when called:

1. If d is one of « NaN𝔻, +∞𝔻, –∞𝔻 », return d.
2. Let inexact be false.
3. If d is +0𝔻 or –0𝔻, then
1. Let qMax be 6111.
2. Let qMin be –6176.
3. If v ≠ 0, set inexact to true.
4. Otherwise:
1. Let e be the unique integer such that 10eabs(v) < 10e + 1.
2. Let qMin be e – 33.
3. If qMin < –6176, set qMin to –6176.
4. Let m be v × 10qMin.
5. Assert: m is an integer.
6. Assert: 0 < abs(m) < 1034.
7. Assert: qMin ≤ 6111.
8. Let n be the largest integer for which m × 10–n is an integer.
9. Let qMax be qMin + n.
10. If qMax > 6111, set qMax to 6111.
11. If v ≠ d, set inexact to true.
5. If inexact is true, then
1. Let q be qMin.
6. Otherwise:
1. Let q be qPreferred.
2. If q < qMin, set q to qMin.
3. If q > qMax, set q to qMax.
7. Return « d, q »𝔻.

# 1.1.3 RoundAndPickQuantum ( d, preferredQuantum [ , roundingMode ] )

The abstract operation RoundAndPickQuantum takes arguments d (a mathematical value) and preferredQuantum (an integer) and optional argument roundingMode (a Decimal128 rounding mode) and returns a Decimal128 value. It rounds the given mathematical value according to the given rounding mode and picks a suitable quantum for the rounded result. It performs the following steps when called:

1. Return PickQuantum(RoundToDecimal128Domain(d, roundingMode), d, preferredQuantum).

# 1.1.4 Decimal128Abs ( argument )

The abstract operation Decimal128Abs takes argument argument (a Decimal128 value) and returns a Decimal128 value. It computes the absolute value of a Decimal128 value It performs the following steps when called:

1. If argument is NaN𝔻, return NaN𝔻.
2. If argument is +∞𝔻 or -∞𝔻, return +∞𝔻.
3. Let v be cohort(argument).
4. Let q be quantum(argument).
5. If v is +0𝔻 or −0𝔻, return « +0𝔻, q »𝔻.
6. Otherwise, return « abs(v), q »𝔻.

# 1.1.5 Decimal128Negate ( argument )

The abstract operation Decimal128Negate takes argument argument (a Decimal128 value) and returns a Decimal128 value. It computes the negation of a Decimal128 value It performs the following steps when called:

1. If argument is NaN𝔻, return NaN𝔻.
2. If argument is +∞𝔻, return -∞𝔻.
3. If argument is -∞𝔻, return +∞𝔻.
4. Let v be cohort(argument).
5. Let q be quantum(argument).
6. If v is +0𝔻, return « −0𝔻, q »𝔻.
7. If v is −0𝔻, return « +0𝔻, q »𝔻.
8. Otherwise, return « −v, q »𝔻.

# 1.1.6 Decimal128ToDecimalString ( argument, preserveTrailingZeroes )

The abstract operation Decimal128ToDecimalString takes arguments argument (a Decimal128 value) and preserveTrailingZeroes (a Boolean) and returns a String. It renders argument as a string in decimal notation, regardless of how many decimal digits would be required. Depending on the value of the second argument, any trailing zeroes will be removed or preserved. It performs the following steps when called:

1. If argument is NaN𝔻, return "NaN".
2. Let sign be sign(_argument).
3. Let argument be Decimal128Abs(argument).
4. If argument is +∞𝔻, return "Infinity".
5. Let v be cohort(argument).
6. Let q be quantum(argument).
7. If v is +0𝔻, then
1. If q ≥ 0, then
1. Return "0".
2. Otherwise:
1. If preserveTrailingZeroes is false, return "0".
2. Let nonIntegerPart be "0" repeated -q times.
3. Return the concatenation of "0", ".", and nonIntegerPart.
8. Let n be the integer for which v × 10q = n.
9. Assert: 0 < n < 1034.
10. Let digits be the unique decimal string representation of n without leading zeroes.
11. Let numDigits be the length of digits.
12. If q ≥ 0, then
1. Let trailingZeroes be the String "0" repeated q times.
2. Return the concatenation of digits and trailingZeroes.
13. Let integerPart be the substring of digits from 0 to numDigits + q.
14. If preserveTrailingZeroes is false and v is an integer, then
1. Assert: integerPart is not "".
2. Return integerPart.
15. If integerPart is "", set integerPart to "0".
16. Let nonIntegerPart be the substring of digits from numDigits + q to numDigits.
17. If preserveTrailingZeroes is false, set nonIntegerPart to a copy of nonIntegerPart with trailing "0"s removed.
18. Assert: nonIntegerPart is not "".
19. Let renderedAbsoluteValue be the concatenation of _integerPart, ".", and nonIntegerPart.
20. If sign = 1, return renderedAbsoluteValue.
21. Otherwise, return the concatenation of "-", renderedAbsoluteValue.

# 1.1.7 Decimal128ToExponentialString ( argument, preserveTrailingZeroes )

The abstract operation Decimal128ToExponentialString takes arguments argument (a Decimal128 value) and preserveTrailingZeroes (a Boolean) and returns a String. It renders argument in exponential notation. It performs the following steps when called:

1. If argument is NaN𝔻, return "NaN".
2. If argument is +∞𝔻, return "Infinity".
3. If argument is -∞𝔻, return "-Infinity".
4. Let v be cohort(argument).
5. Let q be quantum(argument).
6. If v is +0𝔻, return "0".
7. If v is −0𝔻, return "-0".
8. Let coefficientStr be the unique decimal string representation of v without leading zeroes.
9. Let exponentStr be the unique decimal string representation of q without leading zeroes.
10. Return the concatenation of coefficientStr, "e", and exponentStr.

# 1.1.8 Decimal128ValueToObject ( argument )

The abstract operation Decimal128ValueToObject takes argument argument (a Decimal128 value) and returns a Decimal128 object. It converts a Decimal128 value to a Decimal128 object. It performs the following steps when called:

1. Let O be ! OrdinaryCreateFromConstructor(%Decimal128%, "%Decimal128.prototype%", « [[Decimal128Data]] »).
2. Set O.[[Decimal128Data]] to argument.
3. Return O.

# 1.2 The Decimal128 Constructor

The Decimal128 constructor:

• is %Decimal128%.
• is the initial value of the the "Decimal128" property of the global object.
• creates and initializes a new Decimal128 object when called as a constructor
• may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Decimal128 behaviour must include a super call to the Decimal128 constructor to create and initialize the subclass instance with a [[Decimal128Data]] internal slot.

# 1.2.1 Decimal128 ( x )

1. If NewTarget is undefined, throw a TypeError exception.
2. Let toParse be undefined.
3. If x is a BigInt, set toParse to BigInt::toString(x, 10).
4. Otherwise, if x is a Number, set toParse to ! Call(%Number.prototype.toExponential%, x, « »).
5. Otherwise, if x is a String, set toParse to x.
6. If toParse is not a String, throw a TypeError exception.
7. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Decimal128.prototype%", « [[Decimal128Data]] »).
8. If toParse is "NaN", then
1. Set O.[[Decimal128Data]] to NaN𝔻.
9. Else,
1. Let parseResult be ParseText(toParse, StrDecimalLiteral).
2. If parseResult is a List of errors, throw a SyntaxError exception.
3. Let decimalValue be ? StringDecimalValue of parseResult.
4. Set O.[[Decimal128Data]] to decimalValue.
10. Return O.
Note

Given a Number argument, the constructor converts it to a String using the toString method (with no arguments). In some cases, this may not be desited. In some use cases, given a Number, one may wish to call the Decimal128 constructor not with the number but rather with, for instance, the result of calling toFixed or toPrecision on the Number, thereby ensuring a certain level of precision that may get lost when using Number’s toString.

# 1.2.1.1 Runtime Semantics: StringDecimalValue

The syntax-directed operation StringDecimalValue takes no arguments and returns either a normal completion containing a Decimal128 value or a throw completion. It is defined piecewise over the following productions:

StrDecimalLiteral ::: - StrUnsignedDecimalLiteral
1. Let a be ? StringDecimalValue of StrUnsignedDecimalLiteral.
2. If a is +∞𝔻, return -∞𝔻.
3. Assert: a is finite.
4. Let v be cohort(a).
5. Let q be quantum(a).
6. If v is +0𝔻, return « −0𝔻, q »𝔻.
7. Return « −v, q »𝔻.
StrUnsignedDecimalLiteral ::: Infinity
1. Return +∞𝔻.
StrUnsignedDecimalLiteral ::: DecimalDigits . DecimalDigitsopt ExponentPartopt
1. Let a be MV of the first DecimalDigits.
2. If the second DecimalDigits is present, then
1. Let b be MV of the second DecimalDigits.
2. Let n be the number of code points in the second DecimalDigits.
3. Else,
1. Let b be 0.
2. Let n be 0.
4. If ExponentPart is present, let e be MV of ExponentPart. Otherwise, let e be 0.
5. Return RoundAndPickQuantum((a + (b × 10n)) × 10e, en).
StrUnsignedDecimalLiteral ::: . DecimalDigits ExponentPartopt
1. Let b be MV of DecimalDigits.
2. If ExponentPart is present, let e be MV of ExponentPart. Otherwise, let e be 0.
3. Let n be the number of code points in DecimalDigits.
4. Let newValue be b × 10en.
5. Return RoundAndPickQuantum(newValue, en).
StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPartopt
1. Let a be MV of DecimalDigits.
2. If ExponentPart is present, let e be MV of ExponentPart. Otherwise, let e be 0.
3. Return RoundAndPickQuantum(a × 10e, e).

# 2.1 Decimal128.prototype.isNaN ( )

This method returns a Boolean value indicating whether a Decimal128 object represents NaN𝔻.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let d be O.[[Decimal128Data]].
4. If d is NaN𝔻, return true.
5. Otherwise, return false.

# 2.2 Decimal128.prototype.isFinite ( )

This method returns a Boolean value indicating whether a Decimal128 object represents +∞𝔻 or -∞𝔻.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let d be O.[[Decimal128Data]].
4. If d is NaN𝔻, +∞𝔻 or -∞𝔻, return false.
5. Otherwise, return true.

# 2.3 Decimal128.prototype.exponent ( )

This method returns a Number value represents the exponent, which is the integer n for which the current Decimal128 object, x = « v, q »𝔻, there exists a mathematical value s such that v = s × 10e and 1 ≤ abs(s) < 10. This method requires that the Decimal128 value held by the current Decimal128 object is finite and non-zero.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let d be O.[[Decimal128Data]].
4. If d is NaN𝔻, return NaN𝔽.
5. If d is +∞𝔻 or -∞𝔻, return +∞𝔽.
6. Let v be cohort(d).
7. If v is +0𝔻 or −0𝔻, return -∞𝔽.
8. Let e be the unique integer for which there exists a mathematical value s such that v = s × 10e and 1 ≤ abs(s) < 10.
9. Return 𝔽(e).

# 2.4 Decimal128.prototype.mantissa ( )

This method returns a Decimal128 value representing the significand of the current Decimal128 object, which is the mathematical value n for which the current Decimal128 object, x = « v, q »𝔻, there exists an integer e such such that v = s × 10e and 1 ≤ abs(s) < 10. This method requires that the Decimal128 value held by the curernt Decimal128 object is finite and non-zero.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let d be O.[[Decimal128Data]].
4. If d is NaN𝔻, return NaN𝔽.
5. If d is +∞𝔻 or -∞𝔻, return +∞𝔽.
6. Let v be cohort(d).
7. If v is +0𝔻 or −0𝔻, return -∞𝔽.
8. Let s be the unique mathematical value such that v = s × 10e and 1 ≤ abs(s) < 10.
9. Return Decimal128ValueToObjects, −e »𝔻).

# 2.5 Decimal128.prototype.precision

This method returns a Number value representing the quantum of the underlying Decimal128 value.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let d be O.[[Decimal128Data]].
4. If d is NaN𝔻, return NaN𝔽.
5. If d is +∞𝔻 or -∞𝔻, return +∞𝔽.
6. Let q be quantum(d).
7. Return 𝔽(q).

# 2.6 Decimal128.prototype.abs ( )

This method computes the absolute value of a Decimal128 object.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let d be O.[[Decimal128Data]].
4. Return Decimal128ValueToObject(Decimal128Abs(d)).
Note

This operation follows the specification in Section 5.5.1 of IEEE 754-2019.

# 2.7 Decimal128.prototype.negate ( )

This method inverts the sign of a Decimal128 object.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let d be O.[[Decimal128Data]].
4. Return Decimal128ValueToObject(Decimal128Negate(d)).
Note

This operation follows the specification in Section 5.5.1 of IEEE 754-2019.

# 2.8 Decimal128.prototype.add ( x )

This method computes the addition of a Decimal128 object with another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
7. If d1 is +∞𝔻 or d2 is +∞𝔻, then
1. If d1 is -∞𝔻 or d2 is -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
2. Return Decimal128ValueToObject(+∞𝔻).
8. If d1 is -∞𝔻 or d2 is -∞𝔻, then
1. Assert: d1 is not +∞𝔻 and d2 is not +∞𝔻.
2. Return Decimal128ValueToObject(-∞𝔻).
9. Let v1 be cohort(d1).
10. Let v2 be cohort(d2).
11. Let q1 be quantum(d1).
12. Let q2 be quantum(d2).
13. Let newQ be min(q1, q2).
14. If v1 is −0𝔻, return Decimal128ValueToObject(PickQuantum(v2, v2, newQ))..
15. If v2 is −0𝔻, return Decimal128ValueToObject(PickQuantum(v1, v1, newQ)).
16. If v1 is +0𝔻, set v1 to 0.
17. If v2 is +0𝔻, set v2 to 0.
18. Let sum be v1 + v2.
19. If sum = 0, return Decimal128ValueToObject(PickQuantum(+0𝔻, 0, newQ)).
20. Return Decimal128ValueToObject(RoundAndPickQuantum(sum, newQ)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

# 2.9 Decimal128.prototype.subtract ( x )

This method computes subtracts the given Decimal128 object from the current one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
7. If d1 is +∞𝔻 or -∞𝔻, then
1. If d2 is d1, return Decimal128ValueToObject(NaN𝔻).
2. Return Decimal128ValueToObject(d1).
8. If d2 is +∞𝔻, return Decimal128ValueToObject(-∞𝔻).
9. If d2 is -∞𝔻, return Decimal128ValueToObject(+∞𝔻).
10. Let v1 be cohort(d1).
11. Let v2 be cohort(d2).
12. Let q1 be quantum(d1).
13. Let q2 be quantum(d2).
14. Let newQ be min(q1, q2).
15. If v1 is −0𝔻 and v2 is +0𝔻, return Decimal128ValueToObject(PickQuantum(−0𝔻, 0, newQ)).
16. If v1 is +0𝔻 or −0𝔻, set v1 to 0.
17. If v2 is +0𝔻 or −0𝔻, set v2 to 0.
18. Let difference be v1v2.
19. Return Decimal128ValueToObject(RoundAndPickQuantum(difference, newQ)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

# 2.10 Decimal128.prototype.multiply ( x )

This method computes multiplies the current Decimal128 object by another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
7. If d1 or d2 is +∞𝔻, then
1. If d1 or d2 is a zero Decimal128 value, return Decimal128ValueToObject(NaN𝔻).
2. If sign(d1) = -1 or sign(d2) = -1, return Decimal128ValueToObject(-∞𝔻).
3. Return Decimal128ValueToObject(+∞𝔻).
8. If d1 or d2 is -∞𝔻, then
1. If d1 or d2 is a zero Decimal128 value, return Decimal128ValueToObject(NaN𝔻).
2. If sign(d1) = -1 and sign(d2) = -1, return Decimal128ValueToObject(+∞𝔻).
3. Return Decimal128ValueToObject(-∞𝔻).
9. Let v1 be cohort(d1).
10. Let v2 be cohort(d1).
11. Let q1 be quantum(d1).
12. Let q2 be quantum(d2).
13. Let newQ be q1 + q2.
14. If v1 or v2 is +0𝔻, then
1. If sign(d1) = -1 or sign(d2) = -1, return Decimal128ValueToObject(PickQuantum(−0𝔻, 0, newQ)).
2. Return Decimal128ValueToObject(PickQuantum(+0𝔻, 0, newQ)).
15. If v1 or v2 is −0𝔻, then
1. If sign(d1) = -1 and sign(d2) = -1, return Decimal128ValueToObject(PickQuantum(+0𝔻, 0, newQ)).
2. Return Decimal128ValueToObject(PickQuantum(−0𝔻, 0, newQ)).
16. Let product be v1 × v2.
17. Assert: product ≠ 0.
18. Return Decimal128ValueToObject(RoundAndPickQuantum(product, newQ)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

# 2.11 Decimal128.prototype.divide ( x )

This method computes divides the current Decimal128 object by another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
7. If d1 is +∞𝔻, then
1. If d2 is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
2. If sign(d2) = -1, return Decimal128ValueToObject(-∞𝔻).
3. Otherwise, return Decimal128ValueToObject(+∞𝔻).
8. If d1 is -∞𝔻, then
1. If d2 is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
2. If sign(d2) = -1, return Decimal128ValueToObject(+∞𝔻).
3. Otherwise, return Decimal128ValueToObject(-∞𝔻).
9. If d2 is +∞𝔻, then
1. If sign(d1) = -1, return −0𝔻.
2. Otherwise, return +0𝔻.
10. If d2 is -∞𝔻, then
1. If sign(d1) = -1, return +0𝔻.
2. Otherwise, return −0𝔻.
11. Let v1 be cohort(d1).
12. Let v2 be cohort(d2).
13. Let q1 be quantum(d1).
14. Let q2 be quantum(d2).
15. Let newQ be q2q1.
16. If q2 is +0𝔻 or −0𝔻, return Decimal128ValueToObject(NaN𝔻).
17. If v1 is +0𝔻, then
1. If v2 < 0, return Decimal128ValueToObject(PickQuantum(−0𝔻, 0, newQ)).
2. Otherwise, return Decimal128ValueToObject(PickQuantum(+0𝔻, 0, newQ)).
18. If v1 is −0𝔻, then
1. If v2 < 0, return Decimal128ValueToObject(PickQuantum(+0𝔻, 0, newQ)).
2. Otherwise, return Decimal128ValueToObject(PickQuantum(−0𝔻, 0, newQ)).
19. Let quotient be v1 / v2.
20. Return Decimal128ValueToObject(RoundAndPickQuantum(quotient, newQ)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

# 2.12 Decimal128.prototype.remainder ( x )

This method computes the remainder upon dividing the current Decimal128 object by another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
7. If d1 is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
8. If d1 is -∞𝔻 or -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
9. Let v1 be cohort(d1).
10. Let v2 be cohort(d2).
11. Let q1 be quantum(d1).
12. Let q2 be quantum(d2).
13. Let newQ be min(q1, q2).
14. If v2 is +0𝔻 or −0𝔻, return Decimal128ValueToObject(NaN𝔻).
15. If v1 is +0𝔻, return Decimal128ValueToObject(PickQuantum(+0𝔻, 0, newQ)).
16. If v1 is −0𝔻, return Decimal128ValueToObject(PickQuantum(−0𝔻, 0, newQ)).
17. Let remainder be v1 % v2.
18. If remainder = 0, then
1. If v1 < 0, return Decimal128ValueToObject(PickQuantum(−0𝔽, 0, newQ)).
2. Otherwise, return Decimal128ValueToObject(PickQuantum(+0𝔽, 0, newQ)).
19. Return Decimal128ValueToObject(PickQuantum(remainder, remainder, newQ)).
Note

The remainder operation specified here deviates from the IEEE 754-2019 remainder operation (defined there in Section 5.3.1). We follow the the remainder operation for Number rather than IEEE 754, which specifies that, for example, the remainder 46 and 10 is -4 rather than 6.

# 2.13 Decimal128.prototype.compare ( x )

This method returns one of the four Number values -1𝔽, +0𝔽, 1𝔽, and NaN𝔽. It compares the mathematical value of the current Decimal128 object with that of another Decimal128 object.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 is NaN𝔻, return NaN𝔽.
7. If d2 is NaN𝔻, return NaN𝔽.
8. If d1 is +∞𝔻, then
1. If d2 is +∞𝔻, return +0𝔽.
2. Return 1𝔽.
9. If d1 is -∞𝔻, then
1. If d2 is -∞𝔻, return +0𝔽.
2. Return -1𝔽.
10. If d2 is +∞𝔻, return -1𝔽.
11. If d2 is -∞𝔻, return 1𝔽.
12. If the mathematical value of of d1 is less than the mathematical value of d2, return -1𝔽.
13. If the mathematical value of of d2 is less than the mathematical value of d1, return 1𝔽.
14. Otherwise, return +0𝔽.
Note

This operation combines the `compareQuietEqual`, `compareQuietLess` operations in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

# 2.14 Decimal128.prototype.equals ( x )

This method returns either true, false, or undefined according as the current Decimal128 object has the same mathematical value as the given Decimal128 object. The value undefined is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 is NaN𝔻, return undefined.
7. If d2 is NaN𝔻, return undefined.
8. If d1 is +∞𝔻, then
1. If d2 is +∞𝔻, return true.
2. Otherwise, return false.
9. If d1 is -∞𝔻, then
1. If d2 is -∞𝔻, return true.
2. Otherwise, return false.
10. If d2 is +∞𝔻 or -∞𝔻, return false.
11. Let v1 be cohort(d1).
12. Let v2 be cohort(d2).
13. If v1 is +0𝔻 or +0𝔻, then
1. If v2 is either +0𝔻 or −0𝔻, return true.
2. Otherwise, return false.
14. If v2 is +0𝔻 or +0𝔻, return false.
15. If v1 = v2, return true.
16. Otherwise, return false.
Note

This operation corresponds to the `compareQuietEqual` operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

# 2.15 Decimal128.prototype.notEquals ( x )

This method returns either true, false, or undefined according as the current Decimal128 object has a different mathematical value as the given Decimal128 object. The value undefined is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 is NaN𝔻, return undefined.
7. If d2 is NaN𝔻, return undefined.
8. If d1 is +∞𝔻, then
1. If d2 is +∞𝔻, return false.
2. Otherwise, return true.
9. If d1 is -∞𝔻, then
1. If d2 is -∞𝔻, return false.
2. Otherwise, return true.
10. If d2 is +∞𝔻 or -∞𝔻, return true.
11. Let v1 be cohort(d1).
12. Let v2 be cohort(d2).
13. If v1 is +0𝔻 or +0𝔻, then
1. If v2 is either +0𝔻 or −0𝔻, return false.
2. Otherwise, return true.
14. If v2 is +0𝔻 or +0𝔻, return true.
15. If v1 = v2, return false.
16. Otherwise, return true.
Note

This operation corresponds to the `compareQuietNotEqual` operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

# 2.16 Decimal128.prototype.lessThan ( x )

This method returns either true, false, or undefined according as the current Decimal128 object has the same mathematical value as the given Decimal128 object. The value undefined is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 is NaN𝔻, return undefined.
7. If d2 is NaN𝔻, return undefined.
8. If d1 is +∞𝔻, return false.
9. If d1 is -∞𝔻, then
1. If d2 is -∞𝔻, return false.
2. Otherwise, return true.
10. If d2 is +∞𝔻, return true.
11. If d2 is -∞𝔻, return false.
12. Let v1 be cohort(d1).
13. Let v2 be cohort(d2).
14. If v1 is +0𝔻 or +0𝔻, then
1. If v2 is either +0𝔻 or −0𝔻, return false.
2. If v2 > 0, return true.
3. Otherwise, return false.
15. If v2 is +0𝔻 or +0𝔻, then
1. If v1 < 0, return true.
2. Otherwise, return false.
16. If v1 < v2, return true.
17. Otherwise, return false.
Note

This operation corresponds to the `compareQuietEqual` operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

# 2.17 Decimal128.prototype.lessThanOrEqual ( x )

This method returns either true, false, or undefined according as the current Decimal128 object has the same or smaller mathematical value as the given Decimal128 object. The value undefined is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 is NaN𝔻, return undefined.
7. If d2 is NaN𝔻, return undefined.
8. If d1 is +∞𝔻, then
1. If d2 is +∞𝔻, return true.
2. Otherwise, return false.
9. If d1 is -∞𝔻, return true.
10. If d2 is +∞𝔻, return true.
11. If d2 is -∞𝔻, return false.
12. Let v1 be cohort(d1).
13. Let v2 be cohort(d2).
14. If v1 is +0𝔻 or +0𝔻, then
1. If v2 is either +0𝔻 or −0𝔻, return true.
2. If v2 < 0, return true.
3. Otherwise, return false.
15. If v2 is +0𝔻 or +0𝔻, then
1. If v1 < 0, return true.
2. Otherwise, return false.
16. If v1 < v2, return true.
17. Otherwise, return false.
Note

This operation corresponds to the `compareQuietLessEqual` operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

# 2.18 Decimal128.prototype.greaterThan ( x )

This method returns either true, false, or undefined according as the current Decimal128 object has a greater mathematical value as the given Decimal128 object. The value undefined is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 is NaN𝔻, return undefined.
7. If d2 is NaN𝔻, return undefined.
8. If d1 is +∞𝔻, then
1. If d2 is +∞𝔻, return false.
2. Otherwise, return true.
9. If d1 is -∞𝔻, return false.
10. If d2 is +∞𝔻, return false.
11. If d2 is -∞𝔻, return true.
12. Let v1 be cohort(d1).
13. Let v2 be cohort(d2).
14. If v1 is +0𝔻 or +0𝔻, then
1. If v2 is either +0𝔻 or −0𝔻, return false.
2. If v2 < 0, return true.
3. Otherwise, return false.
15. If v2 is +0𝔻 or +0𝔻, then
1. If v1 > 0, return true.
2. Otherwise, return false.
16. If v1 > v2, return true.
17. Otherwise, return false.
Note

This operation corresponds to the `compareQuietGreater` operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

# 2.19 Decimal128.prototype.greaterThanOrEqual ( x )

This method returns either true, false, or undefined according as the current Decimal128 object has a greater or equal mathematical value as the given Decimal128 object. The value undefined is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
4. Let d1 be O.[[Decimal128Data]].
5. Let d2 be x.[[Decimal128Data]].
6. If d1 is NaN𝔻, return undefined.
7. If d2 is NaN𝔻, return undefined.
8. If d1 is +∞𝔻, return true.
9. If d1 is -∞𝔻, return false.
10. If d2 is +∞𝔻, return false.
11. If d2 is -∞𝔻, return true.
12. Let v1 be cohort(d1).
13. Let v2 be cohort(d2).
14. If v1 is +0𝔻 or +0𝔻, then
1. If v2 is either +0𝔻 or −0𝔻, return true.
2. If v2 < 0, return true.
3. Otherwise, return false.
15. If v2 is +0𝔻 or +0𝔻, then
1. If v1 > 0, return true.
2. Otherwise, return false.
16. If v1v2, return true.
17. Otherwise, return false.
Note

This operation corresponds to the `compareQuietGreaterEqual` operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

# 2.20 Decimal128.prototype.round ( numFractionalDigits [ , roundingMode ] )

This method rounds the current Decimal128 object according to the specified rounding mode, which, if omitted, is the default rounding mode, with rounding taking place only after numFractionalDigits non-integer digits, which must be a non-negative integer Number.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. If numFractionalDigits is not a Number, throw a TypeError exception.
4. If numFractionalDigits is not an integer, throw a RangeError exception.
5. If roundingMode is neither undefined nor a String, throw a TypeError exception.
6. If roundingMode is undefined, set roundingMode to the default rounding mode.
7. If roundingMode is not a rounding mode, throw a RangeError exception.
8. Let d be O.[[Decimal128Data]].
9. If d is one of « NaN𝔻, +∞𝔻, -∞𝔻 », return Decimal128ValueToObject(d).
10. Let v be cohort(d).
11. If v is +0𝔻 or −0𝔻, return Decimal128ValueToObjectv, −numFractionalDigits »𝔻).
12. Let sign be sign(d).
13. Let scaledV be v × 10(numFractionalDigits).
14. If sign = -1, set scaledV to −scaledV.
15. Let roundedScaledV be ApplyRoundingModeToPositive(scaledV, roundingMode).
16. If sign = -1, set roundedScaledV to −roundedScaledV.
17. Let rescaledRoundedV be roundedScaledV × 10numFractionalDigits.
18. Return Decimal128ValueToObject(RoundAndPickQuantum(rescaledRoundedV, −numFractionalDigits, roundingMode)).
Note

This operation follows the specification of the rounding mode attributes discussed in Section 4.3 of IEEE 754-2019.

# 2.21 Decimal128.prototype.scale10 ( n )

This method multiplies the current Decimal128 object by 10 raised to the given power.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. If n is not a Number, throw a TypeError exception.
4. If n is not one of « NaN𝔽, +∞𝔽, -∞𝔽 », then
1. If (n) is not an integer, throw a RangeError exception.
5. Let d be O.[[Decimal128Data]].
6. If d is NaN𝔻, +∞𝔻, or -∞𝔻, return Decimal128ValueToObject(d).
7. Let v be cohort(d).
8. Let q be quantum(d).
9. Let newQuantum be q + (n).
10. If v is either +0𝔻 nor −0𝔻, then
1. If n is NaN𝔽, return Decimal128ValueToObject(d).
2. If n is +∞𝔽, return Decimal128ValueToObjectv, 6111 »𝔻).
3. If n is -∞𝔽, return Decimal128ValueToObjectv, -6176 »𝔻).
4. Otherwise, return Decimal128ValueToObject(PickQuantum(v, v, newQuantum)).
11. If n is NaN𝔽, return Decimal128ValueToObject(NaN𝔻).
12. If n is +∞𝔽, then
1. If v > 0, return Decimal128ValueToObject(+∞𝔻).
2. Otherwise, return Decimal128ValueToObject(-∞𝔻).
13. If n is -∞𝔽, then
1. If v > 0, return Decimal128ValueToObject+0𝔻, -6176 »𝔻).
2. Otherwise, return Decimal128ValueToObject−0𝔻, -6176 »𝔻).
14. Let w be v × 10(n).
15. Return Decimal128ValueToObject(RoundAndPickQuantum(w, newQuantum)).
Note

This operation follows the specification of the `scaleB` operation discussed in Section 5.3.3 of IEEE 754-2019.

# 2.22 Decimal128.prototype.toString ( [ options ] )

This method generates a String representation of the current Decimal128 object, in decimal format. Its behaviour is similar to that of Number’s toString by rendering the decimal in decimal notation, but will use exponential notation if the the magnitude of the number is less than 10-6 or greater than 1034.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let preserveTrailingZeroes be false.
4. If options is not undefined, then
1. If options is not an Object, throw a TypeError exception.
2. Set preserveTrailingZeroes to ? Get(options, "preserveTrailingZeroes").
3. If preserveTrailingZeroes is not a Boolean value, throw a TypeError exception.
5. Let d be O.[[Decimal128Data]].
6. If d is NaN𝔻, return "NaN".
7. If d is +∞𝔻, return "Infinity".
8. If d is -∞𝔻, return "-Infinity".
9. Let v be cohort(d).
10. Let q be quantum(d).
11. If v is +0𝔻 or −0𝔻, then
1. Let signPrefix be "".
2. If v is −0𝔻, set signPrefix to "-".
3. If q ≥ 0, return "0".
4. If q > -6, return the concatenation of signPrefix, "0", ".", and the string "0" repeated q times.
5. Otherwise, return the concatenation of signPrefix, "0", "e", and the string representation of q in decimal notation.
12. If abs(v) < 10-6 or abs(v) ≥ 1034, return return Decimal128ToExponentialString(O, preserveTrailingZeroes).
13. Otherwise, return Decimal128ToDecimalString(O, preserveTrailingZeroes).
Note

This operation follows the specification of the conversion of IEEE 754 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

# 2.23 Decimal128.prototype.toExponential ( [ options ] )

This method generates a String representation of the current Decimal128 object, in exponential format (e.g., "123e-4").

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let shouldCanonicalize be true.
4. If options is not undefined, then
1. If options is not an Object, throw a TypeError exception.
2. Set shouldCanonicalize to ? Get(options, "canonicalize").
3. If shouldCanonicalize is not a Boolean value, throw a TypeError exception.
5. Return Decimal128ToExponentialString(O, shouldCanonicalize).
Note

This operation follows the specification of the conversion of IEEE 754 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

# 2.24 Decimal128.prototype.toFixed ( [ options ] )

This method generates a String representation of the current Decimal128 object, in decimal format, with a specified number of digits after the decimal point.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let numDigits be +0𝔽.
4. If options is not undefined, then
1. If options is not an Object, throw a TypeError exception.
2. Set numDigits to ? Get(options, "digits").
3. If numDigits is not a Number, throw a TypeError exception.
5. If numDigits < 0, throw a RangeError exception.
6. If numDigits is not an integer, throw a RangeError exception.
7. Let s be Decimal128ToDecimalString(O, false).
8. If s is "NaN", "Infinity", or "-Infinity", return s.
9. Let integerDigits be "".
10. Let nonIntegerDigits be "".
11. If s contains a ".", then
1. Set integerDigits to the substring of s up to the first occurrence of "." in s.
2. Set nonIntegerDigits to the substring of s after the first occurrence of "." in s.
3. If numDigits > 0, set nonIntegerDigits to the substring of nonIntegerDigits from 0 to numDigits.
12. Else,
1. Set integerDigits to s.
13. If numDigits is 0, return integerDigits.
14. Return the concatenation of integerDigits, ".", and nonIntegerDigits.
Note

This operation follows the specification of the conversion of IEEE 754 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

# 2.25 Decimal128.prototype.toPrecision ( [ options ] )

This method generates a String representation of the current Decimal128 object, in decimal format, with a specified number of significant digits. If the precision argument is omitted or is undefined, this method is equivalent to toString. This method may produce results in exponential notation or decimal notation.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
3. Let shouldCanonicalize be true.
4. If shouldCanonicalize is neither undefined nor a Boolean value, throw a TypeError exception.
5. If precision is neither undefined nor a Number, throw a TypeError exception.
6. If precision is undefined, return Decimal128ToDecimalString(O, shouldCanonicalize).
7. If precision is not an integer, throw a RangeError exception.
8. If precision < 1, throw a RangeError exception.
9. Let d be O.[[Decimal128Data]].
10. If d is NaN𝔻, return "NaN".
11. If d is +∞𝔻, return "Infinity".
12. If d is -∞𝔻, return "-Infinity".
13. Let v be cohort(d).
14. Let q be quantum(d).
15. If v is +0𝔻, return "0".
16. If v is −0𝔻, return "-0".
17. If −q < precision, then
1. Let s be Decimal128ToDecimalString(O, shouldCanonicalize).
2. Let integerDigits be the substring of s up to the first occurrence of "." in s.
3. Let nonIntegerDigits be the substring of s after the first occurrence of "." in s.
4. Let numTrailingZeroesToAdd be precision minus the length of nonIntegerDigits.
5. Let trailingZeroes be the string "0" repeated numTrailingZeroesToAdd times.
6. Return the concatenation of integerDigits, ".", nonIntegerDigits, and trailingZeroes.
18. Let n be the integer such that v × 10q = n and 0 < abs(n) < 1034.
19. Let n1 be the largest multiple of 10 such that nn1 < 10precision.
20. Let v1 be v − (n1 / 10precision).
21. Assert: v1 ≠ 0.
22. Let N be RoundAndPickQuantum(v1, −precision).𝔻.
23. Return Decimal128ToDecimalString(N, shouldCanonicalize).
Note

This operation follows the specification of the conversion of IEEE 754 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

# 2.26 Decimal128.prototype.valueOf ( x )

This method performs the following steps when called:

1. Throw a TypeError exception.

# 3.1.1.1 Number ( value )

This function performs the following steps when called:

1. If value is present, then
1. If value is an object that has an [[Decimal128Data]] internal slot, then
1. Let d be value.[[Decimal128Data]].
2. Let serialized be Decimal128ToExponentialString(d, false).
3. Let n be ! ToNumber(serialized).
2. Else,
1. Let prim be ? ToNumeric(value).
2. If prim is a BigInt, let n be 𝔽((prim)).
3. Otherwise, let n be prim.
2. Else,
1. Let n be +0𝔽.
3. If NewTarget is undefined, return n.
4. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%", « [[NumberData]] »).
5. Set O.[[NumberData]] to n.
6. Return O.

# 3.2.1.1 BigInt ( value )

This function performs the following steps when called:

1. If NewTarget is not undefined, throw a TypeError exception.
2. If value has a [[Decimal128Data]] internal slot, return ? Decimal128ToBigInt(value).
3. Let prim be ? ToPrimitive(value, number).
4. If prim is a Number, return ? NumberToBigInt(prim).
5. Otherwise, return ? ToBigInt(prim).

# 3.2.1.1.1Decimal128ToBigInt ( number )

The abstract operation Decimal128ToBigInt takes argument number (an Object with a [[Decimal128Data]] internal slot) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

1. Let d be number.[[Decimal128Data]].
2. If d is NaN𝔻, +∞𝔻 or -∞𝔻, throw a RangeError exception.
3. Let v be cohort(d).
4. If v is +0𝔻 or −0𝔻, return (0).
5. If v is an integer, return ((v)).
6. Otherwise, throw a RangeError exception.

# 4 Amendments to the ECMAScript® 2024 Internationalization API Specification

Editor's Note

This section lists amendments which must be made to ECMA-402, the ECMAScript® 2024 Internationalization API Specification. Text to be added is marked like this, and text to be deleted is marked like this. Blocks of unmodified text between modified sections are marked by [...].

# 4.1.1.1 ToIntlMathematicalValue ( value )

The abstract operation ToIntlMathematicalValue takes argument value (an ECMAScript language value) and returns either a normal completion containing an Intl mathematical value or a throw completion. It returns value converted to an Intl mathematical value, which is either a mathematical value a finite Decimal128 value, or one of positive-infinity, negative-infinity, not-a-number, and negative-zero. This abstract operation is similar to 7.1.3, but a mathematical value can be returned instead of a Number or BigInt, so that exact decimal values can be represented. It performs the following steps when called:

1. If value has a [[Decimal128Data]] internal slot, then
1. Let d be value.[[Decimal128Data]].
2. If d is NaN𝔻, return not-a-number.
3. If d is +∞𝔻, return positive-infinity.
4. If d is -∞𝔻, return negative-infinity.
5. Return d.
2. Let primValue be ? ToPrimitive(value, number).
3. If Type(primValue) is BigInt, return (primValue).
4. If Type(primValue) is String, then
1. Let str be primValue.
5. Else,
1. Let x be ? ToNumber(primValue).
2. If x is -0𝔽, return negative-zero.
3. Let str be Number::toString(x, 10).
6. Let text be StringToCodePoints(str).
7. Let literal be ParseText(text, StringNumericLiteral).
8. If literal is a List of errors, return not-a-number.
9. Let intlMV be the StringIntlMV of literal.
10. If intlMV is a mathematical value, then
1. Let rounded be RoundMVResult(abs(intlMV)).
2. If rounded is +∞𝔽 and intlMV < 0, return negative-infinity.
3. If rounded is +∞𝔽, return positive-infinity.
4. If rounded is +0𝔽 and intlMV < 0, return negative-zero.
5. If rounded is +0𝔽, return 0.
11. Return intlMV.

# 4.1.1.2 FormatNumericToString ( intlObject, x )

The abstract operation FormatNumericToString takes arguments intlObject (an Object) and x (a mathematical value, negative-zero, or a finite Decimal128 value) and returns a Record with fields [[RoundedNumber]] (a mathematical value or negative-zero) and [[FormattedString]] (a String). It rounds x to an Intl mathematical value according to the internal slots of intlObject. The [[RoundedNumber]] field contains the rounded result value and the [[FormattedString]] field contains a String value representation of that result formatted according to the internal slots of intlObject. It performs the following steps when called:

1. Assert: intlObject has [[RoundingMode]], [[RoundingType]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[RoundingIncrement]], and [[TrailingZeroDisplay]] internal slots.
2. If x is negative-zero, then
1. Let sign be negative.
2. Set x to 0.
3. If x is a Decimal128 value, then
1. Let v be cohort(x).
2. If v is -0𝔻, then
1. Let sign be negative.
2. Set x to 0.
3. Otherwise:
1. if v < 0, set sign to negative.
2. Else, let sign be positive.
4. Else,
1. Assert: x is a mathematical value.
2. If x < 0, let sign be negative; else let sign be positive.
3. If sign is negative, then
1. Set x to -x.
5. Let unsignedRoundingMode be GetUnsignedRoundingMode(intlObject.[[RoundingMode]], sign).
6. If intlObject.[[RoundingType]] is significant-digits, then
1. Let result be ToRawPrecision(x, intlObject.[[MinimumSignificantDigits]], intlObject.[[MaximumSignificantDigits]], unsignedRoundingMode).
7. Else if intlObject.[[RoundingType]] is fraction-digits, then
1. Let result be ToRawFixed(x, intlObject.[[MinimumFractionDigits]], intlObject.[[MaximumFractionDigits]], intlObject.[[RoundingIncrement]], unsignedRoundingMode).
8. Else,
1. Let sResult be ToRawPrecision(x, intlObject.[[MinimumSignificantDigits]], intlObject.[[MaximumSignificantDigits]], unsignedRoundingMode).
2. Let fResult be ToRawFixed(x, intlObject.[[MinimumFractionDigits]], intlObject.[[MaximumFractionDigits]], intlObject.[[RoundingIncrement]], unsignedRoundingMode).
3. If intlObject.[[RoundingType]] is more-precision, then
1. If sResult.[[RoundingMagnitude]]fResult.[[RoundingMagnitude]], then
1. Let result be sResult.
2. Else,
1. Let result be fResult.
4. Else,
1. Assert: intlObject.[[RoundingType]] is less-precision.
2. If sResult.[[RoundingMagnitude]]fResult.[[RoundingMagnitude]], then
1. Let result be fResult.
3. Else,
1. Let result be sResult.
9. Set x to result.[[RoundedNumber]].
10. Let string be result.[[FormattedString]].
11. If intlObject.[[TrailingZeroDisplay]] is "stripIfInteger" and x modulo 1 = 0, then
1. Let i be StringIndexOf(string, ".", 0).
2. If i ≠ -1, set string to the substring of string from 0 to i.
12. Let int be result.[[IntegerDigitsCount]].
13. Let minInteger be intlObject.[[MinimumIntegerDigits]].
14. If int < minInteger, then
1. Let forwardZeros be the String consisting of minInteger - int occurrences of the code unit 0x0030 (DIGIT ZERO).
2. Set string to the string-concatenation of forwardZeros and string.
15. If sign is negative, then
1. If x is 0, set x to negative-zero. Otherwise, set x to -x.
16. Return the Record { [[RoundedNumber]]: x, [[FormattedString]]: string }.

# 4.1.1.3 ToRawPrecision ( x, minPrecision, maxPrecision, unsignedRoundingMode )

The abstract operation ToRawPrecision takes arguments x (a non-negative mathematical value or a finite non-negative Decimal128 value), minPrecision (an integer in the inclusive interval from 1 to 21), maxPrecision (an integer in the inclusive interval from 1 to 21), and unsignedRoundingMode (a specification type from the Unsigned Rounding Mode column of Table 15, or undefined) and returns a Record with fields [[FormattedString]] (a String), [[RoundedNumber]] (a mathematical value), [[IntegerDigitsCount]] (an integer), and [[RoundingMagnitude]] (an integer).

It involves solving the following equation, which returns a valid mathematical value given integer inputs:

ToRawPrecisionFn(n, e, p) = n × 10ep+1
where 10p–1n < 10p

It performs the following steps when called:

1. Let p be maxPrecision.
2. If x is a Decimal128 value, then
1. Let v be cohort(x).
2. Let e be quantum(x).
3. Assert: e ≤ 0.
4. Let n be v × 10-e.
5. Assert: n is an integer.
6. Let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
3. If x = 0, then
1. LetSet m beto the String consisting of p occurrences of the code unit 0x0030 (DIGIT ZERO).
2. LetSet e beto 0.
3. Let xFinal be 0.
4. Else,
1. Let n1 and e1 each be an integer and r1 a mathematical value, with r1 = ToRawPrecisionFn(n1, e1, p), such that r1x and r1 is maximized.
2. Let n2 and e2 each be an integer and r2 a mathematical value, with r2 = ToRawPrecisionFn(n2, e2, p), such that r2x and r2 is minimized.
3. Let r be ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode).
4. If r is r1, then
1. LetSet n beto n1.
2. LetSet e beto e1.
3. Let xFinal be r1.
5. Else,
1. LetSet n beto n2.
2. LetSet e beto e2.
3. Let xFinal be r2.
6. If m is undefined, Letset m beto the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
5. If e ≥ (p - 1), then
1. Set m to the string-concatenation of m and e - p + 1 occurrences of the code unit 0x0030 (DIGIT ZERO).
2. Let int be e + 1.
6. Else if e ≥ 0, then
1. Set m to the string-concatenation of the first e + 1 code units of m, the code unit 0x002E (FULL STOP), and the remaining p - (e + 1) code units of m.
2. Let int be e + 1.
7. Else,
1. Assert: e < 0.
2. Set m to the string-concatenation of "0.", -(e + 1) occurrences of the code unit 0x0030 (DIGIT ZERO), and m.
3. Let int be 1.
8. If m contains the code unit 0x002E (FULL STOP) and maxPrecision > minPrecision, then
1. Let cut be maxPrecision - minPrecision.
2. Repeat, while cut > 0 and the last code unit of m is 0x0030 (DIGIT ZERO),
1. Remove the last code unit from m.
2. Set cut to cut - 1.
3. If the last code unit of m is 0x002E (FULL STOP), then
1. Remove the last code unit from m.
9. Return the Record { [[FormattedString]]: m, [[RoundedNumber]]: xFinal, [[IntegerDigitsCount]]: int, [[RoundingMagnitude]]: ep+1 }.

# 4.1.1.4 ToRawFixed ( x, minFraction, maxFraction, roundingIncrement, unsignedRoundingMode )

The abstract operation ToRawFixed takes arguments x (a non-negative mathematical value or a finite non-negative Decimal128 value), minFraction (an integer in the inclusive interval from 0 to 100), maxFraction (an integer in the inclusive interval from 0 to 100), roundingIncrement (an integer), and unsignedRoundingMode (a specification type from the Unsigned Rounding Mode column of Table 15, or undefined) and returns a Record with fields [[FormattedString]] (a String), [[RoundedNumber]] (a mathematical value), [[IntegerDigitsCount]] (an integer), and [[RoundingMagnitude]] (an integer).

For mathematical values, itIt involves solving the following equation, which returns a valid mathematical value given integer inputs:

ToRawFixedFn(n, f) = n × 10f

For Decimal128 value arguments, it involves rendering them in decimal notation and possibly adjusting the number of fractional digits.

It performs the following steps when called:

1. Let f be maxFraction.
2. If x is a Decimal128 value, then
1. Let v be cohort(x).
2. If v is +0𝔻 or -0𝔻, set v to 0.
3. Let q be quantum(x).
4. Assert: q ≤ 0.
5. Let n be v × 10-q.
6. Assert: n is an integer.
7. Let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
8. Let r be v.
3. Else,
1. Let n1 be an integer and r1 a mathematical value, with r1 = ToRawFixedFn(n1, f), such that n1 modulo roundingIncrement = 0, r1x, and r1 is maximized.
2. Let n2 be an integer and r2 a mathematical value, with r2 = ToRawFixedFn(n2, f), such that n2 modulo roundingIncrement = 0, r2x, and r2 is minimized.
3. Let r be ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode).
4. If r is r1, then
1. Let n to n1.
2. Let xFinal be r1.
5. Else,
1. Let n to n2.
2. Let xFinal be r2.
6. If n = 0, let m be "0". Otherwise, let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
4. If f ≠ 0, then
1. Let k be the length of m.
2. If kf, then
1. Let z be the String value consisting of f + 1 - k occurrences of the code unit 0x0030 (DIGIT ZERO).
2. Set m to the string-concatenation of z and m.
3. Set k to f + 1.
3. Let a be the first k - f code units of m, and let b be the remaining f code units of m.
4. Set m to the string-concatenation of a, ".", and b.
5. Let int be the length of a.
5. Else,
1. Let int be the length of m.
6. Let cut be maxFraction - minFraction.
7. Repeat, while cut > 0 and the last code unit of m is 0x0030 (DIGIT ZERO),
1. Remove the last code unit from m.
2. Set cut to cut - 1.
8. If the last code unit of m is 0x002E (FULL STOP), then
1. Remove the last code unit from m.
9. Return the Record { [[FormattedString]]: m, [[RoundedNumber]]: xFinal, [[IntegerDigitsCount]]: int, [[RoundingMagnitude]]: –f }.

# 4.1.1.5 PartitionNumberPattern ( numberFormat, x )

The abstract operation PartitionNumberPattern takes arguments numberFormat (an object initialized as a NumberFormat) and x (an Intl mathematical value) and returns a List of Records with fields [[Type]] (a String) and [[Value]] (a String). It creates the parts representing the mathematical value of x according to the effective locale and the formatting options of numberFormat. It performs the following steps when called:

1. Let exponent be 0.
2. If x is not-a-number, then
1. Let n be an implementation- and locale-dependent (ILD) String value indicating the NaN value.
3. Else if x is positive-infinity, then
1. Let n be an ILD String value indicating positive infinity.
4. Else if x is negative-infinity, then
1. Let n be an ILD String value indicating negative infinity.
5. Else if x is a Decimal128 value, then
1. Let v be cohort(x).
2. Let q be quantum(x).
3. If numberFormat.[[Style]] is "percent", set x to « v × 100, q + 2 »𝔻.
4. Set exponent to the truncated exponent x.
5. Set x to ! v × 10-exponent.
6. Else,
1. If x is not negative-zero, then
1. Assert: x is a mathematical value.
2. If numberFormat.[[Style]] is "percent", set x be 100 × x.
3. Set exponent to ComputeExponent(numberFormat, x).
4. Set x to x × 10-exponent.
2. Let formatNumberResult be FormatNumericToString(numberFormat, x).
3. Let n be formatNumberResult.[[FormattedString]].
4. Set x to formatNumberResult.[[RoundedNumber]].
7. Let pattern be GetNumberFormatPattern(numberFormat, x).
8. Let result be a new empty List.
9. Let patternParts be PartitionPattern(pattern).
10. For each Record { [[Type]], [[Value]] } patternPart of patternParts, do
1. Let p be patternPart.[[Type]].
2. If p is "literal", then
1. Append the Record { [[Type]]: "literal", [[Value]]: patternPart.[[Value]] } to result.
3. Else if p is equal to "number", then
1. Let notationSubParts be PartitionNotationSubPattern(numberFormat, x, n, exponent).
2. For each Record { [[Type]], [[Value]] } subPart of notationSubParts, do
1. Append subPart to result.
4. Else if p is equal to "plusSign", then
1. Let plusSignSymbol be the ILND String representing the plus sign.
2. Append the Record { [[Type]]: "plusSign", [[Value]]: plusSignSymbol } to result.
5. Else if p is equal to "minusSign", then
1. Let minusSignSymbol be the ILND String representing the minus sign.
2. Append the Record { [[Type]]: "minusSign", [[Value]]: minusSignSymbol } to result.
6. Else if p is equal to "percentSign" and numberFormat.[[Style]] is "percent", then
1. Let percentSignSymbol be the ILND String representing the percent sign.
2. Append the Record { [[Type]]: "percentSign", [[Value]]: percentSignSymbol } to result.
7. Else if p is equal to "unitPrefix" and numberFormat.[[Style]] is "unit", then
1. Let unit be numberFormat.[[Unit]].
2. Let unitDisplay be numberFormat.[[UnitDisplay]].
3. Let mu be an ILD String value representing unit before x in unitDisplay form, which may depend on x in languages having different plural forms.
4. Append the Record { [[Type]]: "unit", [[Value]]: mu } to result.
8. Else if p is equal to "unitSuffix" and numberFormat.[[Style]] is "unit", then
1. Let unit be numberFormat.[[Unit]].
2. Let unitDisplay be numberFormat.[[UnitDisplay]].
3. Let mu be an ILD String value representing unit after x in unitDisplay form, which may depend on x in languages having different plural forms.
4. Append the Record { [[Type]]: "unit", [[Value]]: mu } to result.
9. Else if p is equal to "currencyCode" and numberFormat.[[Style]] is "currency", then
1. Let currency be numberFormat.[[Currency]].
2. Let cd be currency.
3. Append the Record { [[Type]]: "currency", [[Value]]: cd } to result.
10. Else if p is equal to "currencyPrefix" and numberFormat.[[Style]] is "currency", then
1. Let currency be numberFormat.[[Currency]].
2. Let currencyDisplay be numberFormat.[[CurrencyDisplay]].
3. Let cd be an ILD String value representing currency before x in currencyDisplay form, which may depend on x in languages having different plural forms.
4. Append the Record { [[Type]]: "currency", [[Value]]: cd } to result.
11. Else if p is equal to "currencySuffix" and numberFormat.[[Style]] is "currency", then
1. Let currency be numberFormat.[[Currency]].
2. Let currencyDisplay be numberFormat.[[CurrencyDisplay]].
3. Let cd be an ILD String value representing currency after x in currencyDisplay form, which may depend on x in languages having different plural forms. If the implementation does not have such a representation of currency, use currency itself.
4. Append the Record { [[Type]]: "currency", [[Value]]: cd } to result.
12. Else,
1. Let unknown be an ILND String based on x and p.
2. Append the Record { [[Type]]: "unknown", [[Value]]: unknown } to result.
11. Return result.

# 4.2.1.1 ResolvePlural ( pluralRules, n )

The abstract operation ResolvePlural takes arguments pluralRules (an Intl.PluralRules) and n (a Number or an Object with an [[Decimal128Data]] internal slot) and returns a Record with fields [[PluralCategory]] ("zero", "one", "two", "few", "many", or "other") and [[FormattedString]] (a String). The returned Record contains two string-valued fields describing n according to the effective locale and the options of pluralRules: [[PluralCategory]] characterizing its plural category, and [[FormattedString]] containing its formatted representation. It performs the following steps when called:

1. If n is +∞𝔽 or -∞𝔽, then
1. Let s be ! ToString(n).
2. Return the Record { [[PluralCategory]]: "other", [[FormattedString]]: s }.
2. If n is +∞𝔻 or -∞𝔻, then
1. If n is +∞𝔻, let s be "Infinity", otherwise let s be "-Infinity".
2. Return the Record { [[PluralCategory]]: "other", [[FormattedString]]: s }.
3. Let locale be pluralRules.[[Locale]].
4. Let type be pluralRules.[[Type]].
5. If n is a Number, then
1. Let res be FormatNumericToString(pluralRules, (n)).
6. Else,
1. Let res be FormatNumericToString(pluralRules, n).
7. Let s be res.[[FormattedString]].
8. Let operands be GetOperands(s).
9. Let p be PluralRuleSelect(locale, type, n, operands).
10. Return the Record { [[PluralCategory]]: p, [[FormattedString]]: s }.

# 4.2.1.2 ResolvePluralRange ( pluralRules, x, y )

The abstract operation ResolvePluralRange takes arguments pluralRules (an Intl.PluralRules), x (a Number or an Object with a [[Decimal128Data]] internal slot), and y (a Number or an Object with a [[Decimal128Data]] internal slot) and returns either a normal completion containing either "zero", "one", "two", "few", "many", or "other", or a throw completion. The returned String value represents the plural form of the range starting from x and ending at y according to the effective locale and the options of pluralRules. It performs the following steps when called:

1. If x is NaN or NaN𝔻 or y is NaNor NaN𝔻, throw a RangeError exception.
2. Let xp be ResolvePlural(pluralRules, x).
3. Let yp be ResolvePlural(pluralRules, y).
4. If xp.[[FormattedString]] is yp.[[FormattedString]], then
1. Return xp.[[PluralCategory]].
5. Let locale be pluralRules.[[Locale]].
6. Let type be pluralRules.[[Type]].
7. Return PluralRuleSelectRange(locale, type, xp.[[PluralCategory]], yp.[[PluralCategory]]).

© 2024 Jesse Alama, Waldemar Horwat