|
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