From 14f0c06f48aca3e6f015944c88097b404005645e Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Fri, 19 Jan 2024 09:36:03 +0100 Subject: [PATCH] [libc] Fix is_subnormal for Intel Extended Precision (#78592) Also turn a set of `get_biased_exponent() == 0` into `is_subnormal()` which is clearer. --- libc/src/__support/FPUtil/FPBits.h | 28 +++++-------------- libc/src/__support/FPUtil/NormalFloat.h | 4 +-- libc/src/__support/FPUtil/generic/FMA.h | 6 ++-- libc/src/__support/FPUtil/generic/sqrt.h | 2 +- .../FPUtil/generic/sqrt_80_bit_long_double.h | 2 +- .../FPUtil/x86_64/NextAfterLongDouble.h | 3 +- libc/utils/MPFRWrapper/MPFRUtils.cpp | 8 +++--- 7 files changed, 19 insertions(+), 34 deletions(-) diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 3ee6289b7496..be700285de82 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -386,8 +386,11 @@ public: bits = (value & FP_MASK); } - LIBC_INLINE constexpr bool is_zero() const { - return (bits & EXP_SIG_MASK) == 0; + LIBC_INLINE constexpr bool is_zero() const { return exp_sig_bits() == 0; } + + LIBC_INLINE + constexpr bool is_subnormal() const { + return exp_bits() == encode(BiasedExponent::BITS_ALL_ZEROES()); } LIBC_INLINE constexpr bool is_neg() const { return sign().is_neg(); } @@ -435,19 +438,11 @@ public: return exp_sig_bits() == encode(BiasedExponent::BITS_ALL_ONES(), Significand::ZERO()); } - LIBC_INLINE constexpr bool is_zero() const { - return exp_sig_bits() == - encode(BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO()); - } LIBC_INLINE constexpr bool is_finite() const { return exp_bits() != encode(BiasedExponent::BITS_ALL_ONES()); } - LIBC_INLINE - constexpr bool is_subnormal() const { - return exp_bits() == encode(BiasedExponent::BITS_ALL_ZEROES()); - } LIBC_INLINE constexpr bool is_normal() const { - return is_finite() && !is_subnormal(); + return is_finite() && !UP::is_subnormal(); } LIBC_INLINE static constexpr StorageType zero(Sign sign = Sign::POS) { @@ -488,7 +483,7 @@ public: // The function return mantissa with the implicit bit set iff the current // value is a valid normal number. LIBC_INLINE constexpr StorageType get_explicit_mantissa() { - if (is_subnormal()) + if (UP::is_subnormal()) return sig_bits(); return (StorageType(1) << UP::SIG_LEN) | sig_bits(); } @@ -550,18 +545,9 @@ public: return exp_sig_bits() == encode(BiasedExponent::BITS_ALL_ONES(), Significand::MSB()); } - LIBC_INLINE constexpr bool is_zero() const { - return exp_sig_bits() == - encode(BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO()); - } LIBC_INLINE constexpr bool is_finite() const { return !is_inf() && !is_nan(); } - LIBC_INLINE - constexpr bool is_subnormal() const { - return exp_sig_bits() > - encode(BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO()); - } LIBC_INLINE constexpr bool is_normal() const { const auto exp = exp_bits(); if (exp == encode(BiasedExponent::BITS_ALL_ZEROES()) || diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h index 8b1612e1b47c..e7abc53ce612 100644 --- a/libc/src/__support/FPUtil/NormalFloat.h +++ b/libc/src/__support/FPUtil/NormalFloat.h @@ -153,7 +153,7 @@ private: } // Normalize subnormal numbers. - if (bits.get_biased_exponent() == 0) { + if (bits.is_subnormal()) { unsigned shift = evaluate_normalization_shift(bits.get_mantissa()); mantissa = StorageType(bits.get_mantissa()) << shift; exponent = 1 - FPBits::EXP_BIAS - shift; @@ -186,7 +186,7 @@ NormalFloat::init_from_bits(FPBits bits) { return; } - if (bits.get_biased_exponent() == 0) { + if (bits.is_subnormal()) { if (bits.get_implicit_bit() == 0) { // Since we ignore zero value, the mantissa in this case is non-zero. int normalization_shift = diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h index 9c67c645d524..6285cac1983d 100644 --- a/libc/src/__support/FPUtil/generic/FMA.h +++ b/libc/src/__support/FPUtil/generic/FMA.h @@ -104,15 +104,15 @@ template <> LIBC_INLINE double fma(double x, double y, double z) { int z_exp = 0; // Normalize denormal inputs. - if (LIBC_UNLIKELY(FPBits(x).get_biased_exponent() == 0)) { + if (LIBC_UNLIKELY(FPBits(x).is_subnormal())) { x_exp -= 52; x *= 0x1.0p+52; } - if (LIBC_UNLIKELY(FPBits(y).get_biased_exponent() == 0)) { + if (LIBC_UNLIKELY(FPBits(y).is_subnormal())) { y_exp -= 52; y *= 0x1.0p+52; } - if (LIBC_UNLIKELY(FPBits(z).get_biased_exponent() == 0)) { + if (LIBC_UNLIKELY(FPBits(z).is_subnormal())) { z_exp -= 52; z *= 0x1.0p+52; } diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h index f273b678edf5..21ae9d081d3f 100644 --- a/libc/src/__support/FPUtil/generic/sqrt.h +++ b/libc/src/__support/FPUtil/generic/sqrt.h @@ -97,7 +97,7 @@ LIBC_INLINE cpp::enable_if_t, T> sqrt(T x) { StorageType x_mant = bits.get_mantissa(); // Step 1a: Normalize denormal input and append hidden bit to the mantissa - if (bits.get_biased_exponent() == 0) { + if (bits.is_subnormal()) { ++x_exp; // let x_exp be the correct exponent of ONE bit. internal::normalize(x_exp, x_mant); } else { diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h index 4fe9b49ff41c..4f8d136938f5 100644 --- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h +++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h @@ -65,7 +65,7 @@ LIBC_INLINE long double sqrt(long double x) { // Step 1a: Normalize denormal input if (bits.get_implicit_bit()) { x_mant |= ONE; - } else if (bits.get_biased_exponent() == 0) { + } else if (bits.is_subnormal()) { normalize(x_exp, x_mant); } diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h index 5f15bac5df77..512f5de4e793 100644 --- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h +++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h @@ -38,8 +38,7 @@ LIBC_INLINE long double nextafter(long double from, long double to) { return to; // Convert pseudo subnormal number to normal number. - if (from_bits.get_implicit_bit() == 1 && - from_bits.get_biased_exponent() == 0) { + if (from_bits.get_implicit_bit() == 1 && from_bits.is_subnormal()) { from_bits.set_biased_exponent(1); } diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp index fca83c4cdc52..b6ca525db6cf 100644 --- a/libc/utils/MPFRWrapper/MPFRUtils.cpp +++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp @@ -457,9 +457,9 @@ public: int thisExponent = FPBits(thisAsT).get_exponent(); int inputExponent = FPBits(input).get_exponent(); // Adjust the exponents for denormal numbers. - if (FPBits(thisAsT).get_biased_exponent() == 0) + if (FPBits(thisAsT).is_subnormal()) ++thisExponent; - if (FPBits(input).get_biased_exponent() == 0) + if (FPBits(input).is_subnormal()) ++inputExponent; if (thisAsT * input < 0 || thisExponent == inputExponent) { @@ -481,9 +481,9 @@ public: int minExponent = FPBits(min).get_exponent(); int maxExponent = FPBits(max).get_exponent(); // Adjust the exponents for denormal numbers. - if (FPBits(min).get_biased_exponent() == 0) + if (FPBits(min).is_subnormal()) ++minExponent; - if (FPBits(max).get_biased_exponent() == 0) + if (FPBits(max).is_subnormal()) ++maxExponent; MPFRNumber minMPFR(min);