|
13 | 13 | #include "src/__support/CPP/type_traits.h"
|
14 | 14 | #include "src/__support/UInt128.h"
|
15 | 15 | #include "src/__support/common.h"
|
| 16 | +#include "src/__support/libc_assert.h" // LIBC_ASSERT |
16 | 17 | #include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
|
17 | 18 | #include "src/__support/macros/properties/float.h" // LIBC_COMPILER_HAS_FLOAT128
|
18 | 19 | #include "src/__support/math_extras.h" // mask_trailing_ones
|
@@ -266,6 +267,18 @@ template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
|
266 | 267 | LIBC_INLINE constexpr operator Exponent() const {
|
267 | 268 | return Exponent(UP::value - EXP_BIAS);
|
268 | 269 | }
|
| 270 | + |
| 271 | + LIBC_INLINE constexpr BiasedExponent &operator++() { |
| 272 | + LIBC_ASSERT(*this != BiasedExponent(Exponent::INF())); |
| 273 | + ++UP::value; |
| 274 | + return *this; |
| 275 | + } |
| 276 | + |
| 277 | + LIBC_INLINE constexpr BiasedExponent &operator--() { |
| 278 | + LIBC_ASSERT(*this != BiasedExponent(Exponent::SUBNORMAL())); |
| 279 | + --UP::value; |
| 280 | + return *this; |
| 281 | + } |
269 | 282 | };
|
270 | 283 |
|
271 | 284 | // An opaque type to store a floating point significand.
|
@@ -370,6 +383,7 @@ struct FPRepSem : public FPStorage<fp_type> {
|
370 | 383 | protected:
|
371 | 384 | using typename UP::Exponent;
|
372 | 385 | using typename UP::Significand;
|
| 386 | + using UP::bits; |
373 | 387 | using UP::encode;
|
374 | 388 | using UP::exp_bits;
|
375 | 389 | using UP::exp_sig_bits;
|
@@ -435,6 +449,12 @@ struct FPRepSem : public FPStorage<fp_type> {
|
435 | 449 | LIBC_INLINE constexpr bool is_normal() const {
|
436 | 450 | return is_finite() && !is_subnormal();
|
437 | 451 | }
|
| 452 | + LIBC_INLINE constexpr RetT next_toward_inf() const { |
| 453 | + if (is_finite()) |
| 454 | + return RetT(bits + StorageType(1)); |
| 455 | + return RetT(bits); |
| 456 | + } |
| 457 | + |
438 | 458 | // Returns the mantissa with the implicit bit set iff the current
|
439 | 459 | // value is a valid normal number.
|
440 | 460 | LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
|
@@ -551,6 +571,21 @@ struct FPRepSem<FPType::X86_Binary80, RetT>
|
551 | 571 | return false;
|
552 | 572 | return get_implicit_bit();
|
553 | 573 | }
|
| 574 | + LIBC_INLINE constexpr RetT next_toward_inf() const { |
| 575 | + if (is_finite()) { |
| 576 | + if (exp_sig_bits() == max_normal().uintval()) { |
| 577 | + return inf(sign()); |
| 578 | + } else if (exp_sig_bits() == max_subnormal().uintval()) { |
| 579 | + return min_normal(sign()); |
| 580 | + } else if (sig_bits() == SIG_MASK) { |
| 581 | + return RetT(encode(sign(), ++biased_exponent(), Significand::ZERO())); |
| 582 | + } else { |
| 583 | + return RetT(bits + StorageType(1)); |
| 584 | + } |
| 585 | + } |
| 586 | + return RetT(bits); |
| 587 | + } |
| 588 | + |
554 | 589 | LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
|
555 | 590 | return sig_bits();
|
556 | 591 | }
|
@@ -653,6 +688,7 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
|
653 | 688 | using UP::is_signaling_nan;
|
654 | 689 | using UP::is_subnormal;
|
655 | 690 | using UP::is_zero;
|
| 691 | + using UP::next_toward_inf; |
656 | 692 | using UP::sign;
|
657 | 693 | LIBC_INLINE constexpr bool is_inf_or_nan() const { return !is_finite(); }
|
658 | 694 | LIBC_INLINE constexpr bool is_neg() const { return sign().is_neg(); }
|
|
0 commit comments