Skip to content

Commit eb5404d

Browse files
ptomato12wrigja
authored andcommitted
Implement full set of rounding modes in polyfill
This brings the reference polyfill up to date with the new rounding modes. It adds a quick set of tests that only test the internal implementation, in order to make sure that the RoundNumberToIncrement operation behaves as intended. Full tests should test the observable outcome in test262. UPSTREAM_COMMIT=d450be195a81228d284777969bedd9e0475400bd
1 parent a7a50ea commit eb5404d

File tree

3 files changed

+48
-108
lines changed

3 files changed

+48
-108
lines changed

index.d.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
export namespace Temporal {
22
export type ComparisonResult = -1 | 0 | 1;
3-
export type RoundingMode = 'halfExpand' | 'ceil' | 'trunc' | 'floor';
3+
export type RoundingMode =
4+
| 'ceil'
5+
| 'floor'
6+
| 'expand'
7+
| 'trunc'
8+
| 'halfCeil'
9+
| 'halfFloor'
10+
| 'halfExpand'
11+
| 'halfTrunc'
12+
| 'halfEven';
413

514
/**
615
* Options for assigning fields using `with()` or entire objects with

lib/ecmascript.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,12 @@ export function ToTemporalRoundingMode(
842842
options: { roundingMode?: Temporal.RoundingMode },
843843
fallback: Temporal.RoundingMode
844844
) {
845-
return GetOption(options, 'roundingMode', ['ceil', 'floor', 'trunc', 'halfExpand'], fallback);
845+
return GetOption(
846+
options,
847+
'roundingMode',
848+
['ceil', 'floor', 'expand', 'trunc', 'halfCeil', 'halfFloor', 'halfExpand', 'halfTrunc', 'halfEven'],
849+
fallback
850+
);
846851
}
847852

848853
function NegateTemporalRoundingMode(roundingMode: Temporal.RoundingMode) {
@@ -851,6 +856,10 @@ function NegateTemporalRoundingMode(roundingMode: Temporal.RoundingMode) {
851856
return 'floor';
852857
case 'floor':
853858
return 'ceil';
859+
case 'halfCeil':
860+
return 'halfFloor';
861+
case 'halfFloor':
862+
return 'halfCeil';
854863
default:
855864
return roundingMode;
856865
}
@@ -5317,19 +5326,46 @@ function RoundNumberToIncrement(quantity: JSBI, increment: number, mode: Tempora
53175326
let { quotient, remainder } = divmod(quantity, JSBI.BigInt(increment));
53185327
if (JSBI.equal(remainder, ZERO)) return quantity;
53195328
const sign = JSBI.lessThan(remainder, ZERO) ? -1 : 1;
5329+
const tiebreaker = abs(JSBI.multiply(remainder, JSBI.BigInt(2)));
5330+
const tie = JSBI.equal(tiebreaker, JSBI.BigInt(increment));
5331+
const expandIsNearer = JSBI.greaterThan(tiebreaker, JSBI.BigInt(increment));
53205332
switch (mode) {
53215333
case 'ceil':
53225334
if (sign > 0) quotient = JSBI.add(quotient, JSBI.BigInt(sign));
53235335
break;
53245336
case 'floor':
53255337
if (sign < 0) quotient = JSBI.add(quotient, JSBI.BigInt(sign));
53265338
break;
5339+
case 'expand':
5340+
// always expand if there is a remainder
5341+
quotient = JSBI.add(quotient, JSBI.BigInt(sign));
5342+
break;
53275343
case 'trunc':
53285344
// no change needed, because divmod is a truncation
53295345
break;
5346+
case 'halfCeil':
5347+
if (expandIsNearer || (tie && sign > 0)) {
5348+
quotient = JSBI.add(quotient, JSBI.BigInt(sign));
5349+
}
5350+
break;
5351+
case 'halfFloor':
5352+
if (expandIsNearer || (tie && sign < 0)) {
5353+
quotient = JSBI.add(quotient, JSBI.BigInt(sign));
5354+
}
5355+
break;
53305356
case 'halfExpand':
53315357
// "half up away from zero"
5332-
if (JSBI.toNumber(abs(JSBI.multiply(remainder, JSBI.BigInt(2)))) >= increment) {
5358+
if (expandIsNearer || tie) {
5359+
quotient = JSBI.add(quotient, JSBI.BigInt(sign));
5360+
}
5361+
break;
5362+
case 'halfTrunc':
5363+
if (expandIsNearer) {
5364+
quotient = JSBI.add(quotient, JSBI.BigInt(sign));
5365+
}
5366+
break;
5367+
case 'halfEven':
5368+
if (expandIsNearer || (tie && JSBI.toNumber(JSBI.remainder(abs(quotient), JSBI.BigInt(2))) === 1)) {
53335369
quotient = JSBI.add(quotient, JSBI.BigInt(sign));
53345370
}
53355371
break;

0 commit comments

Comments
 (0)