1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef builtin_temporal_TemporalRoundingMode_h
8 #define builtin_temporal_TemporalRoundingMode_h
10 #include "mozilla/Assertions.h"
15 #include "builtin/temporal/Int128.h"
17 namespace js::temporal
{
19 // Overview of integer rounding modes is available at
20 // <https://en.wikipedia.org/wiki/Rounding#Rounding_to_integer>.
21 enum class TemporalRoundingMode
{
22 // 1. Directed rounding to an integer.
24 // Round toward positive infinity.
27 // Round toward negative infinity.
30 // Round toward infinity or round away from zero.
33 // Round toward zero or round away from infinity.
36 // 2. Rounding to the nearest integer.
38 // Round half toward positive infinity.
41 // Round half toward negative infinity.
44 // Round half toward infinity or round half away from zero.
47 // Round half toward zero or round half away from infinity.
50 // Round half to even.
55 * NegateTemporalRoundingMode ( roundingMode )
57 constexpr auto NegateTemporalRoundingMode(TemporalRoundingMode roundingMode
) {
59 switch (roundingMode
) {
60 case TemporalRoundingMode::Ceil
:
61 return TemporalRoundingMode::Floor
;
63 case TemporalRoundingMode::Floor
:
64 return TemporalRoundingMode::Ceil
;
66 case TemporalRoundingMode::HalfCeil
:
67 return TemporalRoundingMode::HalfFloor
;
69 case TemporalRoundingMode::HalfFloor
:
70 return TemporalRoundingMode::HalfCeil
;
72 case TemporalRoundingMode::Expand
:
73 case TemporalRoundingMode::Trunc
:
74 case TemporalRoundingMode::HalfExpand
:
75 case TemporalRoundingMode::HalfTrunc
:
76 case TemporalRoundingMode::HalfEven
:
79 MOZ_CRASH("invalid rounding mode");
83 * Adjust the rounding mode to round negative values in the same direction as
86 constexpr auto ToPositiveRoundingMode(TemporalRoundingMode roundingMode
) {
87 switch (roundingMode
) {
88 case TemporalRoundingMode::Ceil
:
89 case TemporalRoundingMode::Floor
:
90 case TemporalRoundingMode::HalfCeil
:
91 case TemporalRoundingMode::HalfFloor
:
92 case TemporalRoundingMode::HalfEven
:
93 // (Half-)Ceil/Floor round toward the same infinity for negative and
94 // positive values, so the rounding mode doesn't need to be adjusted. The
95 // same applies for half-even rounding.
98 case TemporalRoundingMode::Expand
:
99 // Expand rounds positive values toward +infinity, but negative values
100 // toward -infinity. Adjust the rounding mode to Ceil to round negative
101 // values in the same direction as positive values.
102 return TemporalRoundingMode::Ceil
;
104 case TemporalRoundingMode::Trunc
:
105 // Truncation rounds positive values down toward zero, but negative values
106 // up toward zero. Adjust the rounding mode to Floor to round negative
107 // values in the same direction as positive values.
108 return TemporalRoundingMode::Floor
;
110 case TemporalRoundingMode::HalfExpand
:
111 // Adjust the rounding mode to Half-Ceil, similar to the Expand case.
112 return TemporalRoundingMode::HalfCeil
;
114 case TemporalRoundingMode::HalfTrunc
:
115 // Adjust the rounding mode to Half-Floor, similar to the Trunc case.
116 return TemporalRoundingMode::HalfFloor
;
118 MOZ_CRASH("unexpected rounding mode");
121 // Temporal performs division on "mathematical values" [1] with implies using
122 // infinite precision. This rules out using IEE-754 floating point types like
123 // `double`. It also means we can't implement the algorithms from the
124 // specification verbatim, but instead have to translate them into equivalent
127 // Throughout the following division functions, the divisor is required to be
128 // positive. This allows to simplify the implementation, because it ensures
129 // non-zero quotient and remainder values have the same sign as the dividend.
131 // [1] https://tc39.es/ecma262/#mathematical-value
134 * Compute ceiling division ⌈dividend / divisor⌉. The divisor must be a positive
137 constexpr int64_t CeilDiv(int64_t dividend
, int64_t divisor
) {
138 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
140 // NB: Division and modulo operation are fused into a single machine code
141 // instruction by the compiler.
142 int64_t quotient
= dividend
/ divisor
;
143 int64_t remainder
= dividend
% divisor
;
145 // Ceiling division rounds the quotient toward positive infinity. When the
146 // quotient is negative, this is equivalent to rounding toward zero. See [1].
148 // int64_t division truncates, so rounding toward zero for negative quotients
149 // is already covered. When there is a non-zero positive remainder, the
150 // quotient is positive and we have to increment it by one to implement
151 // rounding toward positive infinity.
154 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
162 * Compute floor division ⌊dividend / divisor⌋. The divisor must be a positive
165 constexpr int64_t FloorDiv(int64_t dividend
, int64_t divisor
) {
166 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
168 // NB: Division and modulo operation are fused into a single machine code
169 // instruction by the compiler.
170 int64_t quotient
= dividend
/ divisor
;
171 int64_t remainder
= dividend
% divisor
;
173 // Floor division rounds the quotient toward negative infinity. When the
174 // quotient is positive, this is equivalent to rounding toward zero. See [1].
176 // int64_t division truncates, so rounding toward zero for positive quotients
177 // is already covered. When there is a non-zero negative remainder, the
178 // quotient is negative and we have to decrement it by one to implement
179 // rounding toward negative infinity.
182 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
190 * Compute "round toward infinity" division `dividend / divisor`. The divisor
191 * must be a positive number.
193 constexpr int64_t ExpandDiv(int64_t dividend
, int64_t divisor
) {
194 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
196 // NB: Division and modulo operation are fused into a single machine code
197 // instruction by the compiler.
198 int64_t quotient
= dividend
/ divisor
;
199 int64_t remainder
= dividend
% divisor
;
201 // "Round toward infinity" division rounds positive quotients toward positive
202 // infinity and negative quotients toward negative infinity. See [1].
204 // When there is a non-zero positive remainder, the quotient is positive and
205 // we have to increment it by one to implement rounding toward positive
206 // infinity. When there is a non-zero negative remainder, the quotient is
207 // negative and we have to decrement it by one to implement rounding toward
208 // negative infinity.
211 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
222 * Compute truncating division `dividend / divisor`. The divisor must be a
225 constexpr int64_t TruncDiv(int64_t dividend
, int64_t divisor
) {
226 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
228 // Truncating division rounds both positive and negative quotients toward
231 // int64_t division truncates, so rounding toward zero implicitly happens.
234 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
235 return dividend
/ divisor
;
239 * Compute "round half toward positive infinity" division `dividend / divisor`.
240 * The divisor must be a positive number.
242 inline int64_t HalfCeilDiv(int64_t dividend
, int64_t divisor
) {
243 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
245 // NB: Division and modulo operation are fused into a single machine code
246 // instruction by the compiler.
247 int64_t quotient
= dividend
/ divisor
;
248 int64_t remainder
= dividend
% divisor
;
250 // "Round half toward positive infinity" division rounds the quotient toward
251 // positive infinity when the fractional part of the remainder is ≥0.5. When
252 // the quotient is negative, this is equivalent to rounding toward zero
253 // instead of toward positive infinity. See [1].
255 // When the remainder is a non-zero positive value, the quotient is positive,
256 // too. When additionally the fractional part of the remainder is ≥0.5, we
257 // have to increment the quotient by one to implement rounding toward positive
260 // int64_t division truncates, so we implicitly round toward zero for negative
261 // quotients. When the absolute value of the fractional part of the remainder
262 // is >0.5, we should instead have rounded toward negative infinity, so we
263 // need to decrement the quotient by one.
266 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
267 if (remainder
> 0 && uint64_t(std::abs(remainder
)) * 2 >= uint64_t(divisor
)) {
270 if (remainder
< 0 && uint64_t(std::abs(remainder
)) * 2 > uint64_t(divisor
)) {
277 * Compute "round half toward negative infinity" division `dividend / divisor`.
278 * The divisor must be a positive number.
280 inline int64_t HalfFloorDiv(int64_t dividend
, int64_t divisor
) {
281 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
283 // NB: Division and modulo operation are fused into a single machine code
284 // instruction by the compiler.
285 int64_t quotient
= dividend
/ divisor
;
286 int64_t remainder
= dividend
% divisor
;
288 // "Round half toward negative infinity" division rounds the quotient toward
289 // negative infinity when the fractional part of the remainder is ≥0.5. When
290 // the quotient is positive, this is equivalent to rounding toward zero
291 // instead of toward negative infinity. See [1].
293 // When the remainder is a non-zero negative value, the quotient is negative,
294 // too. When additionally the fractional part of the remainder is ≥0.5, we
295 // have to decrement the quotient by one to implement rounding toward negative
298 // int64_t division truncates, so we implicitly round toward zero for positive
299 // quotients. When the absolute value of the fractional part of the remainder
300 // is >0.5, we should instead have rounded toward positive infinity, so we
301 // need to increment the quotient by one.
304 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
305 if (remainder
< 0 && uint64_t(std::abs(remainder
)) * 2 >= uint64_t(divisor
)) {
308 if (remainder
> 0 && uint64_t(std::abs(remainder
)) * 2 > uint64_t(divisor
)) {
315 * Compute "round half toward infinity" division `dividend / divisor`. The
316 * divisor must be a positive number.
318 inline int64_t HalfExpandDiv(int64_t dividend
, int64_t divisor
) {
319 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
321 // NB: Division and modulo operation are fused into a single machine code
322 // instruction by the compiler.
323 int64_t quotient
= dividend
/ divisor
;
324 int64_t remainder
= dividend
% divisor
;
326 // "Round half toward infinity" division rounds positive quotients whose
327 // remainder has a fractional part ≥0.5 toward positive infinity. And negative
328 // quotients whose remainder has a fractional part ≥0.5 toward negative
329 // infinity. See [1].
331 // int64_t division truncates, which means it rounds toward zero, so we have
332 // to increment resp. decrement the quotient when the fractional part of the
333 // remainder is ≥0.5 to round toward ±infinity.
336 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
337 if (uint64_t(std::abs(remainder
)) * 2 >= uint64_t(divisor
)) {
338 quotient
+= (dividend
> 0) ? 1 : -1;
344 * Compute "round half toward zero" division `dividend / divisor`. The divisor
345 * must be a positive number.
347 inline int64_t HalfTruncDiv(int64_t dividend
, int64_t divisor
) {
348 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
350 // NB: Division and modulo operation are fused into a single machine code
351 // instruction by the compiler.
352 int64_t quotient
= dividend
/ divisor
;
353 int64_t remainder
= dividend
% divisor
;
355 // "Round half toward zero" division rounds both positive and negative
356 // quotients whose remainder has a fractional part ≤0.5 toward zero. See [1].
358 // int64_t division truncates, so we implicitly round toward zero. When the
359 // fractional part of the remainder is >0.5, we should instead have rounded
360 // toward ±infinity, so we need to increment resp. decrement the quotient by
364 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
365 if (uint64_t(std::abs(remainder
)) * 2 > uint64_t(divisor
)) {
366 quotient
+= (dividend
> 0) ? 1 : -1;
372 * Compute "round half to even" division `dividend / divisor`. The divisor must
373 * be a positive number.
375 inline int64_t HalfEvenDiv(int64_t dividend
, int64_t divisor
) {
376 MOZ_ASSERT(divisor
> 0, "negative divisor not supported");
378 // NB: Division and modulo operation are fused into a single machine code
379 // instruction by the compiler.
380 int64_t quotient
= dividend
/ divisor
;
381 int64_t remainder
= dividend
% divisor
;
383 // "Round half to even" division rounds both positive and negative quotients
384 // to the nearest even integer. See [1].
386 // int64_t division truncates, so we implicitly round toward zero. When the
387 // fractional part of the remainder is 0.5 and the quotient is odd or when the
388 // fractional part of the remainder is >0.5, we should instead have rounded
389 // toward ±infinity, so we need to increment resp. decrement the quotient by
393 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
394 if ((quotient
& 1) == 1 &&
395 uint64_t(std::abs(remainder
)) * 2 == uint64_t(divisor
)) {
396 quotient
+= (dividend
> 0) ? 1 : -1;
398 if (uint64_t(std::abs(remainder
)) * 2 > uint64_t(divisor
)) {
399 quotient
+= (dividend
> 0) ? 1 : -1;
405 * Perform `dividend / divisor` and round the result according to the given
408 inline int64_t Divide(int64_t dividend
, int64_t divisor
,
409 TemporalRoundingMode roundingMode
) {
410 switch (roundingMode
) {
411 case TemporalRoundingMode::Ceil
:
412 return CeilDiv(dividend
, divisor
);
413 case TemporalRoundingMode::Floor
:
414 return FloorDiv(dividend
, divisor
);
415 case TemporalRoundingMode::Expand
:
416 return ExpandDiv(dividend
, divisor
);
417 case TemporalRoundingMode::Trunc
:
418 return TruncDiv(dividend
, divisor
);
419 case TemporalRoundingMode::HalfCeil
:
420 return HalfCeilDiv(dividend
, divisor
);
421 case TemporalRoundingMode::HalfFloor
:
422 return HalfFloorDiv(dividend
, divisor
);
423 case TemporalRoundingMode::HalfExpand
:
424 return HalfExpandDiv(dividend
, divisor
);
425 case TemporalRoundingMode::HalfTrunc
:
426 return HalfTruncDiv(dividend
, divisor
);
427 case TemporalRoundingMode::HalfEven
:
428 return HalfEvenDiv(dividend
, divisor
);
430 MOZ_CRASH("invalid rounding mode");
434 * Compute ceiling division ⌈dividend / divisor⌉. The divisor must be a positive
437 constexpr Int128
CeilDiv(const Int128
& dividend
, const Int128
& divisor
) {
438 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
440 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
442 // Ceiling division rounds the quotient toward positive infinity. When the
443 // quotient is negative, this is equivalent to rounding toward zero. See [1].
445 // Int128 division truncates, so rounding toward zero for negative quotients
446 // is already covered. When there is a non-zero positive remainder, the
447 // quotient is positive and we have to increment it by one to implement
448 // rounding toward positive infinity.
451 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
452 if (remainder
> Int128
{0}) {
453 quotient
+= Int128
{1};
459 * Compute floor division ⌊dividend / divisor⌋. The divisor must be a positive
462 constexpr Int128
FloorDiv(const Int128
& dividend
, const Int128
& divisor
) {
463 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
465 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
467 // Floor division rounds the quotient toward negative infinity. When the
468 // quotient is positive, this is equivalent to rounding toward zero. See [1].
470 // Int128 division truncates, so rounding toward zero for positive quotients
471 // is already covered. When there is a non-zero negative remainder, the
472 // quotient is negative and we have to decrement it by one to implement
473 // rounding toward negative infinity.
476 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
477 if (remainder
< Int128
{0}) {
478 quotient
-= Int128
{1};
484 * Compute "round toward infinity" division `dividend / divisor`. The divisor
485 * must be a positive number.
487 constexpr Int128
ExpandDiv(const Int128
& dividend
, const Int128
& divisor
) {
488 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
490 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
492 // "Round toward infinity" division rounds positive quotients toward positive
493 // infinity and negative quotients toward negative infinity. See [1].
495 // When there is a non-zero positive remainder, the quotient is positive and
496 // we have to increment it by one to implement rounding toward positive
497 // infinity. When there is a non-zero negative remainder, the quotient is
498 // negative and we have to decrement it by one to implement rounding toward
499 // negative infinity.
502 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
503 if (remainder
> Int128
{0}) {
504 quotient
+= Int128
{1};
506 if (remainder
< Int128
{0}) {
507 quotient
-= Int128
{1};
513 * Compute truncating division `dividend / divisor`. The divisor must be a
516 constexpr Int128
TruncDiv(const Int128
& dividend
, const Int128
& divisor
) {
517 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
519 // Truncating division rounds both positive and negative quotients toward
522 // Int128 division truncates, so rounding toward zero implicitly happens.
525 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
526 return dividend
/ divisor
;
530 * Compute "round half toward positive infinity" division `dividend / divisor`.
531 * The divisor must be a positive number.
533 inline Int128
HalfCeilDiv(const Int128
& dividend
, const Int128
& divisor
) {
534 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
536 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
538 // "Round half toward positive infinity" division rounds the quotient toward
539 // positive infinity when the fractional part of the remainder is ≥0.5. When
540 // the quotient is negative, this is equivalent to rounding toward zero
541 // instead of toward positive infinity. See [1].
543 // When the remainder is a non-zero positive value, the quotient is positive,
544 // too. When additionally the fractional part of the remainder is ≥0.5, we
545 // have to increment the quotient by one to implement rounding toward positive
548 // Int128 division truncates, so we implicitly round toward zero for negative
549 // quotients. When the absolute value of the fractional part of the remainder
550 // is >0.5, we should instead have rounded toward negative infinity, so we
551 // need to decrement the quotient by one.
554 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
555 if (remainder
> Int128
{0} &&
556 Uint128(remainder
.abs()) * Uint128
{2} >= static_cast<Uint128
>(divisor
)) {
557 quotient
+= Int128
{1};
559 if (remainder
< Int128
{0} &&
560 Uint128(remainder
.abs()) * Uint128
{2} > static_cast<Uint128
>(divisor
)) {
561 quotient
-= Int128
{1};
567 * Compute "round half toward negative infinity" division `dividend / divisor`.
568 * The divisor must be a positive number.
570 inline Int128
HalfFloorDiv(const Int128
& dividend
, const Int128
& divisor
) {
571 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
573 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
575 // "Round half toward negative infinity" division rounds the quotient toward
576 // negative infinity when the fractional part of the remainder is ≥0.5. When
577 // the quotient is positive, this is equivalent to rounding toward zero
578 // instead of toward negative infinity. See [1].
580 // When the remainder is a non-zero negative value, the quotient is negative,
581 // too. When additionally the fractional part of the remainder is ≥0.5, we
582 // have to decrement the quotient by one to implement rounding toward negative
585 // Int128 division truncates, so we implicitly round toward zero for positive
586 // quotients. When the absolute value of the fractional part of the remainder
587 // is >0.5, we should instead have rounded toward positive infinity, so we
588 // need to increment the quotient by one.
591 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
592 if (remainder
< Int128
{0} &&
593 Uint128(remainder
.abs()) * Uint128
{2} >= static_cast<Uint128
>(divisor
)) {
594 quotient
-= Int128
{1};
596 if (remainder
> Int128
{0} &&
597 Uint128(remainder
.abs()) * Uint128
{2} > static_cast<Uint128
>(divisor
)) {
598 quotient
+= Int128
{1};
604 * Compute "round half toward infinity" division `dividend / divisor`. The
605 * divisor must be a positive number.
607 inline Int128
HalfExpandDiv(const Int128
& dividend
, const Int128
& divisor
) {
608 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
610 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
612 // "Round half toward infinity" division rounds positive quotients whose
613 // remainder has a fractional part ≥0.5 toward positive infinity. And negative
614 // quotients whose remainder has a fractional part ≥0.5 toward negative
615 // infinity. See [1].
617 // Int128 division truncates, which means it rounds toward zero, so we have
618 // to increment resp. decrement the quotient when the fractional part of the
619 // remainder is ≥0.5 to round toward ±infinity.
622 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
623 if (Uint128(remainder
.abs()) * Uint128
{2} >= static_cast<Uint128
>(divisor
)) {
624 quotient
+= (dividend
> Int128
{0}) ? Int128
{1} : Int128
{-1};
630 * Compute "round half toward zero" division `dividend / divisor`. The divisor
631 * must be a positive number.
633 inline Int128
HalfTruncDiv(const Int128
& dividend
, const Int128
& divisor
) {
634 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
636 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
638 // "Round half toward zero" division rounds both positive and negative
639 // quotients whose remainder has a fractional part ≤0.5 toward zero. See [1].
641 // Int128 division truncates, so we implicitly round toward zero. When the
642 // fractional part of the remainder is >0.5, we should instead have rounded
643 // toward ±infinity, so we need to increment resp. decrement the quotient by
647 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
648 if (Uint128(remainder
.abs()) * Uint128
{2} > static_cast<Uint128
>(divisor
)) {
649 quotient
+= (dividend
> Int128
{0}) ? Int128
{1} : Int128
{-1};
655 * Compute "round half to even" division `dividend / divisor`. The divisor must
656 * be a positive number.
658 inline Int128
HalfEvenDiv(const Int128
& dividend
, const Int128
& divisor
) {
659 MOZ_ASSERT(divisor
> Int128
{0}, "negative divisor not supported");
661 auto [quotient
, remainder
] = dividend
.divrem(divisor
);
663 // "Round half to even" division rounds both positive and negative quotients
664 // to the nearest even integer. See [1].
666 // Int128 division truncates, so we implicitly round toward zero. When the
667 // fractional part of the remainder is 0.5 and the quotient is odd or when the
668 // fractional part of the remainder is >0.5, we should instead have rounded
669 // toward ±infinity, so we need to increment resp. decrement the quotient by
673 // https://tc39.es/proposal-temporal/#table-temporal-unsigned-rounding-modes
674 if ((quotient
& Int128
{1}) == Int128
{1} &&
675 Uint128(remainder
.abs()) * Uint128
{2} == static_cast<Uint128
>(divisor
)) {
676 quotient
+= (dividend
> Int128
{0}) ? Int128
{1} : Int128
{-1};
678 if (Uint128(remainder
.abs()) * Uint128
{2} > static_cast<Uint128
>(divisor
)) {
679 quotient
+= (dividend
> Int128
{0}) ? Int128
{1} : Int128
{-1};
685 * Perform `dividend / divisor` and round the result according to the given
688 inline Int128
Divide(const Int128
& dividend
, const Int128
& divisor
,
689 TemporalRoundingMode roundingMode
) {
690 switch (roundingMode
) {
691 case TemporalRoundingMode::Ceil
:
692 return CeilDiv(dividend
, divisor
);
693 case TemporalRoundingMode::Floor
:
694 return FloorDiv(dividend
, divisor
);
695 case TemporalRoundingMode::Expand
:
696 return ExpandDiv(dividend
, divisor
);
697 case TemporalRoundingMode::Trunc
:
698 return TruncDiv(dividend
, divisor
);
699 case TemporalRoundingMode::HalfCeil
:
700 return HalfCeilDiv(dividend
, divisor
);
701 case TemporalRoundingMode::HalfFloor
:
702 return HalfFloorDiv(dividend
, divisor
);
703 case TemporalRoundingMode::HalfExpand
:
704 return HalfExpandDiv(dividend
, divisor
);
705 case TemporalRoundingMode::HalfTrunc
:
706 return HalfTruncDiv(dividend
, divisor
);
707 case TemporalRoundingMode::HalfEven
:
708 return HalfEvenDiv(dividend
, divisor
);
710 MOZ_CRASH("invalid rounding mode");
713 } /* namespace js::temporal */
715 #endif /* builtin_temporal_TemporalRoundingMode_h */