diff --git a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp index affef6fcf549e..b773043bda67d 100644 --- a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp +++ b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp @@ -28,7 +28,7 @@ using LIBC_NAMESPACE::fputil::FPBits; // exponent. Subnormals have a lower effective precision since they don't // necessarily use all of the bits of the mantissa. template inline constexpr int effective_precision(int exponent) { - const int full_precision = FPBits::MANTISSA_PRECISION; + const int full_precision = FPBits::FRACTION_LEN + 1; // This is intended to be 0 when the exponent is the lowest normal and // increase as the exponent's magnitude increases. diff --git a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h index 1798310c3e31e..ef9593a42b005 100644 --- a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h +++ b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h @@ -31,7 +31,7 @@ LIBC_INLINE T remquo(T x, T y, int &q) { if (ybits.is_nan()) return y; if (xbits.is_inf() || ybits.is_zero()) - return FPBits::build_quiet_nan(1); + return FPBits::build_quiet_nan(fputil::Sign::POS, 1).get_val(); if (xbits.is_zero()) { q = 0; diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 2465158bb2cdf..0a79b505ecbe1 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -390,7 +390,7 @@ struct FPRepSem : public FPStorage { return exp_bits() == encode(BiasedExp::BITS_ALL_ZEROES()); } LIBC_INLINE constexpr bool is_normal() const { - return is_finite() && !UP::is_subnormal(); + return is_finite() && !is_subnormal(); } // Returns the mantissa with the implicit bit set iff the current // value is a valid normal number. @@ -556,6 +556,14 @@ struct FPRep : public FPRepSem { using UP::FRACTION_MASK; using UP::SIGN_MASK; + // Comparison + LIBC_INLINE constexpr friend bool operator==(FPRep a, FPRep b) { + return a.uintval() == b.uintval(); + } + LIBC_INLINE constexpr friend bool operator!=(FPRep a, FPRep b) { + return a.uintval() != b.uintval(); + } + // Representation LIBC_INLINE constexpr StorageType uintval() const { return bits & FP_MASK; } LIBC_INLINE constexpr void set_uintval(StorageType value) { @@ -698,16 +706,6 @@ struct FPBits final : public internal::FPRep(), FPBits> { using UP::bits; // Constants. - LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_PRECISION = - UP::FRACTION_LEN + 1; - LIBC_INLINE_VAR static constexpr StorageType MIN_NORMAL = - UP::min_normal(Sign::POS).uintval(); - LIBC_INLINE_VAR static constexpr StorageType MAX_NORMAL = - UP::max_normal(Sign::POS).uintval(); - LIBC_INLINE_VAR static constexpr StorageType MIN_SUBNORMAL = - UP::min_subnormal(Sign::POS).uintval(); - LIBC_INLINE_VAR static constexpr StorageType MAX_SUBNORMAL = - UP::max_subnormal(Sign::POS).uintval(); LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT = (1 << UP::EXP_LEN) - 1; @@ -731,37 +729,6 @@ struct FPBits final : public internal::FPRep(), FPBits> { LIBC_INLINE constexpr explicit operator T() const { return get_val(); } - // Methods below this are used by tests. - // TODO: inline and remove. - LIBC_INLINE static constexpr T one(Sign sign = Sign::POS) { - return T(UP::one(sign)); - } - LIBC_INLINE static constexpr T zero(Sign sign = Sign::POS) { - return T(UP::zero(sign)); - } - LIBC_INLINE static constexpr T inf(Sign sign = Sign::POS) { - return T(UP::inf(sign)); - } - LIBC_INLINE static constexpr T min_normal() { - return T(UP::min_normal(Sign::POS)); - } - LIBC_INLINE static constexpr T max_normal() { - return T(UP::max_normal(Sign::POS)); - } - LIBC_INLINE static constexpr T min_denormal() { - return T(UP::min_subnormal(Sign::POS)); - } - LIBC_INLINE static constexpr T max_denormal() { - return T(UP::max_subnormal(Sign::POS)); - } - LIBC_INLINE static constexpr T build_nan(StorageType v) { - return T(UP::build_nan(Sign::POS, v)); - } - LIBC_INLINE static constexpr T build_quiet_nan(StorageType v, - Sign sign = Sign::POS) { - return T(UP::build_quiet_nan(sign, v)); - } - // TODO: Use an uint32_t for 'biased_exp'. LIBC_INLINE static constexpr FPBits create_value(Sign sign, StorageType biased_exp, StorageType mantissa) { diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h index c38a40dfb0898..82237dec09e42 100644 --- a/libc/src/__support/FPUtil/Hypot.h +++ b/libc/src/__support/FPUtil/Hypot.h @@ -197,7 +197,7 @@ LIBC_INLINE T hypot(T x, T y) { if (int round_mode = quick_get_round(); round_mode == FE_TONEAREST || round_mode == FE_UPWARD) return T(FPBits_t::inf()); - return T(FPBits_t(FPBits_t::MAX_NORMAL)); + return T(FPBits_t::max_normal()); } } else { // For denormal result, we simply move the leading bit of the result to @@ -254,7 +254,7 @@ LIBC_INLINE T hypot(T x, T y) { if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) { if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD) return T(FPBits_t::inf()); - return T(FPBits_t(FPBits_t::MAX_NORMAL)); + return T(FPBits_t::max_normal()); } } diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h index 81c8281f3c7bb..d7114625a9b31 100644 --- a/libc/src/__support/FPUtil/ManipulationFunctions.h +++ b/libc/src/__support/FPUtil/ManipulationFunctions.h @@ -108,7 +108,7 @@ LIBC_INLINE T logb(T x) { return x; } else if (bits.is_inf()) { // Return positive infinity. - return T(FPBits::inf(Sign::POS)); + return T(FPBits::inf()); } NormalFloat normal(bits); @@ -127,7 +127,7 @@ LIBC_INLINE T ldexp(T x, int exp) { // that adding |exp| to it does not lead to integer rollover. But, if |exp| // value is larger the exponent range for type T, then we can return infinity // early. Because the result of the ldexp operation can be a subnormal number, - // we need to accommodate the (mantissaWidht + 1) worth of shift in + // we need to accommodate the (mantissaWidth + 1) worth of shift in // calculating the limit. int exp_limit = FPBits::MAX_BIASED_EXPONENT + FPBits::FRACTION_LEN + 1; if (exp > exp_limit) @@ -164,26 +164,22 @@ LIBC_INLINE T nextafter(T from, U to) { return static_cast(to); using StorageType = typename FPBits::StorageType; - StorageType int_val = from_bits.uintval(); - if (from != FPBits::zero()) { - if ((static_cast(from) < to) == (from > FPBits::zero())) { - ++int_val; + if (from != T(0)) { + if ((static_cast(from) < to) == (from > T(0))) { + from_bits = FPBits(StorageType(from_bits.uintval() + 1)); } else { - --int_val; + from_bits = FPBits(StorageType(from_bits.uintval() - 1)); } } else { - int_val = FPBits::MIN_SUBNORMAL; - if (to_bits.is_neg()) - int_val |= FPBits::SIGN_MASK; + from_bits = FPBits::min_subnormal(to_bits.sign()); } - StorageType exponent_bits = int_val & FPBits::EXP_MASK; - if (exponent_bits == StorageType(0)) + if (from_bits.is_subnormal()) raise_except_if_required(FE_UNDERFLOW | FE_INEXACT); - else if (exponent_bits == FPBits::EXP_MASK) + else if (from_bits.is_inf()) raise_except_if_required(FE_OVERFLOW | FE_INEXACT); - return cpp::bit_cast(int_val); + return from_bits.get_val(); } } // namespace fputil diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h index cfa9e14175105..fa4da33b5b17f 100644 --- a/libc/src/__support/FPUtil/NormalFloat.h +++ b/libc/src/__support/FPUtil/NormalFloat.h @@ -215,7 +215,7 @@ template <> LIBC_INLINE NormalFloat::operator long double() const { // Max exponent is of the form 0xFF...E. That is why -2 and not -1. constexpr int MAX_EXPONENT_VALUE = (1 << LDBits::EXP_LEN) - 2; if (biased_exponent > MAX_EXPONENT_VALUE) { - return LDBits::inf(sign); + return LDBits::inf(sign).get_val(); } FPBits result(0.0l); diff --git a/libc/src/__support/FPUtil/aarch64/FEnvImpl.h b/libc/src/__support/FPUtil/aarch64/FEnvImpl.h index 23cde88c9c7c5..e0eec17e038c6 100644 --- a/libc/src/__support/FPUtil/aarch64/FEnvImpl.h +++ b/libc/src/__support/FPUtil/aarch64/FEnvImpl.h @@ -155,8 +155,8 @@ LIBC_INLINE int set_except(int excepts) { LIBC_INLINE int raise_except(int excepts) { float zero = 0.0f; float one = 1.0f; - float largeValue = FPBits::max_normal(); - float smallValue = FPBits::min_normal(); + float largeValue = FPBits::max_normal().get_val(); + float smallValue = FPBits::min_normal().get_val(); auto divfunc = [](float a, float b) { __asm__ __volatile__("ldr s0, %0\n\t" "ldr s1, %1\n\t" diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h index 5449f5561d569..888d7ffec241e 100644 --- a/libc/src/__support/FPUtil/dyadic_float.h +++ b/libc/src/__support/FPUtil/dyadic_float.h @@ -93,7 +93,7 @@ template struct DyadicFloat { return 0.0; // Assume that it is normalized, and output is also normal. - constexpr uint32_t PRECISION = FPBits::MANTISSA_PRECISION; + constexpr uint32_t PRECISION = FPBits::FRACTION_LEN + 1; using output_bits_t = typename FPBits::StorageType; int exp_hi = exponent + static_cast((Bits - 1) + FPBits::EXP_BIAS); diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h index 89849540315f6..1e0381194009d 100644 --- a/libc/src/__support/FPUtil/except_value_utils.h +++ b/libc/src/__support/FPUtil/except_value_utils.h @@ -102,15 +102,13 @@ template struct ExceptValues { // Helper functions to set results for exceptional cases. template LIBC_INLINE T round_result_slightly_down(T value_rn) { volatile T tmp = value_rn; - const T MIN_NORMAL = FPBits::min_normal(); - tmp = tmp - MIN_NORMAL; + tmp -= FPBits::min_normal().get_val(); return tmp; } template LIBC_INLINE T round_result_slightly_up(T value_rn) { volatile T tmp = value_rn; - const T MIN_NORMAL = FPBits::min_normal(); - tmp = tmp + MIN_NORMAL; + tmp += FPBits::min_normal().get_val(); return tmp; } diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h index 6285cac1983d1..5c36463ea5021 100644 --- a/libc/src/__support/FPUtil/generic/FMA.h +++ b/libc/src/__support/FPUtil/generic/FMA.h @@ -130,9 +130,9 @@ template <> LIBC_INLINE double fma(double x, double y, double z) { return x * y + z; // Extract mantissa and append hidden leading bits. - UInt128 x_mant = x_bits.get_mantissa() | FPBits::MIN_NORMAL; - UInt128 y_mant = y_bits.get_mantissa() | FPBits::MIN_NORMAL; - UInt128 z_mant = z_bits.get_mantissa() | FPBits::MIN_NORMAL; + UInt128 x_mant = x_bits.get_explicit_mantissa(); + UInt128 y_mant = y_bits.get_explicit_mantissa(); + UInt128 z_mant = z_bits.get_explicit_mantissa(); // If the exponent of the product x*y > the exponent of z, then no extra // precision beside the entire product x*y is needed. On the other hand, when @@ -255,9 +255,7 @@ template <> LIBC_INLINE double fma(double x, double y, double z) { if ((round_mode == FE_TOWARDZERO) || (round_mode == FE_UPWARD && prod_sign.is_neg()) || (round_mode == FE_DOWNWARD && prod_sign.is_pos())) { - result = FPBits::MAX_NORMAL; - return prod_sign.is_neg() ? -cpp::bit_cast(result) - : cpp::bit_cast(result); + return FPBits::max_normal(prod_sign).get_val(); } return static_cast(FPBits::inf(prod_sign)); } diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h index f4000b97751ef..18355b801dbc7 100644 --- a/libc/src/__support/FPUtil/generic/FMod.h +++ b/libc/src/__support/FPUtil/generic/FMod.h @@ -124,7 +124,7 @@ template struct FModExceptionalInputHandler { LIBC_INLINE static bool pre_check(T x, T y, T &out) { using FPB = fputil::FPBits; - const T quiet_nan = FPB::build_quiet_nan(0); + const T quiet_nan = FPB::build_quiet_nan().get_val(); FPB sx(x), sy(y); if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() && !sx.is_inf_or_nan())) { diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h index 21ae9d081d3f1..0a0690ec1463b 100644 --- a/libc/src/__support/FPUtil/generic/sqrt.h +++ b/libc/src/__support/FPUtil/generic/sqrt.h @@ -71,15 +71,19 @@ LIBC_INLINE cpp::enable_if_t, T> sqrt(T x) { return x86::sqrt(x); } else { // IEEE floating points formats. - using StorageType = typename FPBits::StorageType; - constexpr StorageType ONE = StorageType(1) << FPBits::FRACTION_LEN; + using Sign = fputil::Sign; + using FPBits_t = typename fputil::FPBits; + using StorageType = typename FPBits_t::StorageType; + constexpr StorageType ONE = StorageType(1) << FPBits_t::FRACTION_LEN; + constexpr auto FLT_NAN = + FPBits_t::build_quiet_nan(Sign::POS, ONE >> 1).get_val(); - FPBits bits(x); + FPBits_t bits(x); if (bits.is_inf_or_nan()) { if (bits.is_neg() && (bits.get_mantissa() == 0)) { // sqrt(-Inf) = NaN - return FPBits::build_quiet_nan(ONE >> 1); + return FLT_NAN; } else { // sqrt(NaN) = NaN // sqrt(+Inf) = +Inf @@ -91,7 +95,7 @@ LIBC_INLINE cpp::enable_if_t, T> sqrt(T x) { return x; } else if (bits.is_neg()) { // sqrt( negative numbers ) = NaN - return FPBits::build_quiet_nan(ONE >> 1); + return FLT_NAN; } else { int x_exp = bits.get_exponent(); StorageType x_mant = bits.get_mantissa(); @@ -145,10 +149,10 @@ LIBC_INLINE cpp::enable_if_t, T> sqrt(T x) { } // Remove hidden bit and append the exponent field. - x_exp = ((x_exp >> 1) + FPBits::EXP_BIAS); + x_exp = ((x_exp >> 1) + FPBits_t::EXP_BIAS); y = (y - ONE) | - (static_cast(x_exp) << FPBits::FRACTION_LEN); + (static_cast(x_exp) << FPBits_t::FRACTION_LEN); switch (quick_get_round()) { case FE_TONEAREST: 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 4f8d136938f56..b0a3776029ca7 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 @@ -38,14 +38,16 @@ LIBC_INLINE long double sqrt(long double x); LIBC_INLINE long double sqrt(long double x) { using LDBits = FPBits; using StorageType = typename LDBits::StorageType; + using Sign = fputil::Sign; constexpr StorageType ONE = StorageType(1) << int(LDBits::FRACTION_LEN); + constexpr auto LDNAN = LDBits::build_quiet_nan(Sign::POS, ONE >> 1).get_val(); - FPBits bits(x); + LDBits bits(x); if (bits.is_inf_or_nan()) { if (bits.is_neg() && (bits.get_mantissa() == 0)) { // sqrt(-Inf) = NaN - return LDBits::build_quiet_nan(ONE >> 1); + return LDNAN; } else { // sqrt(NaN) = NaN // sqrt(+Inf) = +Inf @@ -57,7 +59,7 @@ LIBC_INLINE long double sqrt(long double x) { return x; } else if (bits.is_neg()) { // sqrt( negative numbers ) = NaN - return LDBits::build_quiet_nan(ONE >> 1); + return LDNAN; } else { int x_exp = bits.get_explicit_exponent(); StorageType x_mant = bits.get_mantissa(); diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h index 512f5de4e7931..d1c76ba954b93 100644 --- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h +++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h @@ -43,16 +43,18 @@ LIBC_INLINE long double nextafter(long double from, long double to) { } using StorageType = FPBits::StorageType; - constexpr StorageType SIGN_VAL = (StorageType(1) << 79); + constexpr StorageType FRACTION_MASK = FPBits::FRACTION_MASK; - StorageType int_val = from_bits.uintval(); - if (from < 0.0l) { - if (from > to) { - if (int_val == (SIGN_VAL + FPBits::MAX_SUBNORMAL)) { + // StorageType int_val = from_bits.uintval(); + if (from == 0.0l) { // +0.0 / -0.0 + from_bits = FPBits::min_subnormal(from > to ? Sign::NEG : Sign::POS); + } else if (from < 0.0l) { + if (to < from) { // toward -inf + if (from_bits == FPBits::max_subnormal(Sign::NEG)) { // We deal with normal/subnormal boundary separately to avoid // dealing with the implicit bit. - int_val = SIGN_VAL + FPBits::MIN_NORMAL; - } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) { + from_bits = FPBits::min_normal(Sign::NEG); + } else if (from_bits.get_mantissa() == FRACTION_MASK) { from_bits.set_mantissa(0); // Incrementing exponent might overflow the value to infinity, // which is what is expected. Since NaNs are handling separately, @@ -62,45 +64,40 @@ LIBC_INLINE long double nextafter(long double from, long double to) { raise_except_if_required(FE_OVERFLOW | FE_INEXACT); return from_bits.get_val(); } else { - ++int_val; + from_bits = FPBits(StorageType(from_bits.uintval() + 1)); } - } else { - if (int_val == (SIGN_VAL + FPBits::MIN_NORMAL)) { + } else { // toward +inf + if (from_bits == FPBits::min_normal(Sign::NEG)) { // We deal with normal/subnormal boundary separately to avoid // dealing with the implicit bit. - int_val = SIGN_VAL + FPBits::MAX_SUBNORMAL; - } else if ((int_val & FRACTION_MASK) == 0) { + from_bits = FPBits::max_subnormal(Sign::NEG); + } else if (from_bits.get_mantissa() == 0) { from_bits.set_mantissa(FRACTION_MASK); // from == 0 is handled separately so decrementing the exponent will not // lead to underflow. from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1); return from_bits.get_val(); } else { - --int_val; + from_bits = FPBits(StorageType(from_bits.uintval() - 1)); } } - } else if (from == 0.0l) { - if (from > to) - int_val = SIGN_VAL + 1; - else - int_val = 1; } else { - if (from > to) { - if (int_val == FPBits::MIN_NORMAL) { - int_val = FPBits::MAX_SUBNORMAL; - } else if ((int_val & FRACTION_MASK) == 0) { + if (to < from) { // toward -inf + if (from_bits == FPBits::min_normal(Sign::POS)) { + from_bits = FPBits::max_subnormal(Sign::POS); + } else if (from_bits.get_mantissa() == 0) { from_bits.set_mantissa(FRACTION_MASK); // from == 0 is handled separately so decrementing the exponent will not // lead to underflow. from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1); return from_bits.get_val(); } else { - --int_val; + from_bits = FPBits(StorageType(from_bits.uintval() - 1)); } - } else { - if (int_val == FPBits::MAX_SUBNORMAL) { - int_val = FPBits::MIN_NORMAL; - } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) { + } else { // toward +inf + if (from_bits == FPBits::max_subnormal(Sign::POS)) { + from_bits = FPBits::min_normal(Sign::POS); + } else if (from_bits.get_mantissa() == FRACTION_MASK) { from_bits.set_mantissa(0); // Incrementing exponent might overflow the value to infinity, // which is what is expected. Since NaNs are handling separately, @@ -110,16 +107,15 @@ LIBC_INLINE long double nextafter(long double from, long double to) { raise_except_if_required(FE_OVERFLOW | FE_INEXACT); return from_bits.get_val(); } else { - ++int_val; + from_bits = FPBits(StorageType(from_bits.uintval() + 1)); } } } - StorageType implicit_bit = int_val & (StorageType(1) << FPBits::FRACTION_LEN); - if (implicit_bit == StorageType(0)) + if (!from_bits.get_implicit_bit()) raise_except_if_required(FE_UNDERFLOW | FE_INEXACT); - return cpp::bit_cast(int_val); + return from_bits.get_val(); } } // namespace fputil diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h index 53951dc131c28..a153dfc363d73 100644 --- a/libc/src/__support/common.h +++ b/libc/src/__support/common.h @@ -25,7 +25,6 @@ #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \ LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ __##name##_impl__ __asm__(#name); \ - decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ type __##name##_impl__ arglist #else #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index 8aeb3d2cea03d..9655c993bee28 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -1167,7 +1167,7 @@ LIBC_INLINE StrToNumResult strtofloatingpoint(const char *__restrict src) { index = left_paren; } } - result = FPBits(result.build_quiet_nan(nan_mantissa, result.sign())); + result = FPBits(result.build_quiet_nan(result.sign(), nan_mantissa)); } } else if (tolower(src[index]) == 'i') { // INF if (tolower(src[index + 1]) == inf_string[1] && @@ -1215,7 +1215,7 @@ template LIBC_INLINE StrToNumResult strtonan(const char *arg) { nan_mantissa = static_cast(nan_mantissa_result); } - result = FPBits(result.build_quiet_nan(nan_mantissa)); + result = FPBits::build_quiet_nan(fputil::Sign::POS, nan_mantissa); return {T(result), 0, error}; } diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp index 67832596a67fb..7b2a09101182e 100644 --- a/libc/src/math/generic/acosf.cpp +++ b/libc/src/math/generic/acosf.cpp @@ -85,7 +85,7 @@ LLVM_LIBC_FUNCTION(float, acosf, (float x)) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); } - return x + FPBits::build_quiet_nan(0); + return x + FPBits::build_quiet_nan().get_val(); } // When 0.5 < |x| < 1, we perform range reduction as follow: diff --git a/libc/src/math/generic/acoshf.cpp b/libc/src/math/generic/acoshf.cpp index b0b87095fbb07..a546cc2268b04 100644 --- a/libc/src/math/generic/acoshf.cpp +++ b/libc/src/math/generic/acoshf.cpp @@ -29,7 +29,7 @@ LLVM_LIBC_FUNCTION(float, acoshf, (float x)) { // x < 1. fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits_t::build_quiet_nan(0); + return FPBits_t::build_quiet_nan().get_val(); } if (LIBC_UNLIKELY(x_u >= 0x4f8ffb03)) { diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp index bc0d27c1eebc5..ee8e853063644 100644 --- a/libc/src/math/generic/asinf.cpp +++ b/libc/src/math/generic/asinf.cpp @@ -109,7 +109,7 @@ LLVM_LIBC_FUNCTION(float, asinf, (float x)) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); } - return x + FPBits::build_nan(FPBits::FRACTION_MASK); + return x + FPBits::build_nan(Sign::POS, FPBits::FRACTION_MASK).get_val(); } // Check for exceptional values diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp index fd6f5c96b6b4e..cd0acbf24e928 100644 --- a/libc/src/math/generic/atanhf.cpp +++ b/libc/src/math/generic/atanhf.cpp @@ -29,11 +29,11 @@ LLVM_LIBC_FUNCTION(float, atanhf, (float x)) { if (x_abs == 0x3F80'0000U) { fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return FPBits::inf(sign); + return FPBits::inf(sign).get_val(); } else { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits::build_quiet_nan(0); + return FPBits::build_quiet_nan().get_val(); } } diff --git a/libc/src/math/generic/cosf.cpp b/libc/src/math/generic/cosf.cpp index 89333ab19e89f..132e72c0f65da 100644 --- a/libc/src/math/generic/cosf.cpp +++ b/libc/src/math/generic/cosf.cpp @@ -118,7 +118,7 @@ LLVM_LIBC_FUNCTION(float, cosf, (float x)) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); } - return x + FPBits::build_quiet_nan(0); + return x + FPBits::build_quiet_nan().get_val(); } // Combine the results with the sine of sum formula: diff --git a/libc/src/math/generic/coshf.cpp b/libc/src/math/generic/coshf.cpp index 3b01852e9f544..a618056a64dc8 100644 --- a/libc/src/math/generic/coshf.cpp +++ b/libc/src/math/generic/coshf.cpp @@ -32,16 +32,16 @@ LLVM_LIBC_FUNCTION(float, coshf, (float x)) { } if (xbits.is_inf_or_nan()) - return x + FPBits::inf(); + return x + FPBits::inf().get_val(); int rounding = fputil::quick_get_round(); if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); - return x + FPBits::inf(); + return x + FPBits::inf().get_val(); } // TODO: We should be able to reduce the latency and reciprocal throughput diff --git a/libc/src/math/generic/exp.cpp b/libc/src/math/generic/exp.cpp index a1b4d9a64f969..49ea1699bb209 100644 --- a/libc/src/math/generic/exp.cpp +++ b/libc/src/math/generic/exp.cpp @@ -205,7 +205,7 @@ double set_exceptional(double x) { return x; if (fputil::quick_get_round() == FE_UPWARD) - return FPBits::min_denormal(); + return FPBits::min_subnormal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_UNDERFLOW); return 0.0; @@ -216,7 +216,7 @@ double set_exceptional(double x) { if (x_u < 0x7ff0'0000'0000'0000ULL) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); diff --git a/libc/src/math/generic/exp10.cpp b/libc/src/math/generic/exp10.cpp index e441f2c0edc7d..f1da03cba0b30 100644 --- a/libc/src/math/generic/exp10.cpp +++ b/libc/src/math/generic/exp10.cpp @@ -248,7 +248,7 @@ double set_exceptional(double x) { return x; if (fputil::quick_get_round() == FE_UPWARD) - return FPBits::min_denormal(); + return FPBits::min_subnormal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_UNDERFLOW); return 0.0; @@ -262,7 +262,7 @@ double set_exceptional(double x) { if (x_u < 0x7ff0'0000'0000'0000ULL) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); diff --git a/libc/src/math/generic/exp10f_impl.h b/libc/src/math/generic/exp10f_impl.h index 2861659a6e57e..ff4c1c3aec67c 100644 --- a/libc/src/math/generic/exp10f_impl.h +++ b/libc/src/math/generic/exp10f_impl.h @@ -42,7 +42,7 @@ LIBC_INLINE float exp10f(float x) { if (xbits.is_nan()) return x; if (fputil::fenv_is_round_up()) - return FPBits::min_denormal(); + return FPBits::min_subnormal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_UNDERFLOW); return 0.0f; @@ -53,13 +53,13 @@ LIBC_INLINE float exp10f(float x) { if (x_u < 0x7f80'0000U) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); } // x is +inf or nan - return x + FPBits::inf(); + return x + FPBits::inf().get_val(); } } diff --git a/libc/src/math/generic/exp2.cpp b/libc/src/math/generic/exp2.cpp index 70bc4870806a9..508bff9bd9fc9 100644 --- a/libc/src/math/generic/exp2.cpp +++ b/libc/src/math/generic/exp2.cpp @@ -223,7 +223,7 @@ double set_exceptional(double x) { return x; if (fputil::quick_get_round() == FE_UPWARD) - return FPBits::min_denormal(); + return FPBits::min_subnormal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_UNDERFLOW); return 0.0; @@ -237,7 +237,7 @@ double set_exceptional(double x) { if (x_u < 0x7ff0'0000'0000'0000ULL) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); diff --git a/libc/src/math/generic/exp2f_impl.h b/libc/src/math/generic/exp2f_impl.h index 86360840b96e6..d2342e289fcba 100644 --- a/libc/src/math/generic/exp2f_impl.h +++ b/libc/src/math/generic/exp2f_impl.h @@ -76,13 +76,13 @@ LIBC_INLINE float exp2f(float x) { if (x_u < 0x7f80'0000U) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); } // x is +inf or nan - return x + FPBits::inf(); + return x + FPBits::inf().get_val(); } // x <= -150 if (x_u >= 0xc316'0000U) { @@ -93,7 +93,7 @@ LIBC_INLINE float exp2f(float x) { if (xbits.is_nan()) return x; if (fputil::fenv_is_round_up()) - return FPBits::min_denormal(); + return FPBits::min_subnormal().get_val(); if (x != 0.0f) { fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_UNDERFLOW); diff --git a/libc/src/math/generic/expf.cpp b/libc/src/math/generic/expf.cpp index 88d408994fe42..f3ce8400d0a41 100644 --- a/libc/src/math/generic/expf.cpp +++ b/libc/src/math/generic/expf.cpp @@ -50,7 +50,7 @@ LLVM_LIBC_FUNCTION(float, expf, (float x)) { if (xbits.is_nan()) return x; if (fputil::fenv_is_round_up()) - return FPBits::min_denormal(); + return FPBits::min_subnormal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_UNDERFLOW); return 0.0f; @@ -61,7 +61,7 @@ LLVM_LIBC_FUNCTION(float, expf, (float x)) { if (xbits.uintval() < 0x7f80'0000U) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); diff --git a/libc/src/math/generic/expm1.cpp b/libc/src/math/generic/expm1.cpp index d9fccf98e8caa..c1fb80309d7b4 100644 --- a/libc/src/math/generic/expm1.cpp +++ b/libc/src/math/generic/expm1.cpp @@ -267,13 +267,13 @@ double set_exceptional(double x) { if (x_u < 0x7ff0'0000'0000'0000ULL) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); } // x is +inf or nan - return x + static_cast(FPBits::inf()); + return x + FPBits::inf().get_val(); } } // namespace diff --git a/libc/src/math/generic/expm1f.cpp b/libc/src/math/generic/expm1f.cpp index c6e0663ec46c3..037e60021b296 100644 --- a/libc/src/math/generic/expm1f.cpp +++ b/libc/src/math/generic/expm1f.cpp @@ -68,12 +68,12 @@ LLVM_LIBC_FUNCTION(float, expm1f, (float x)) { if (xbits.uintval() < 0x7f80'0000U) { int rounding = fputil::quick_get_round(); if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); } - return x + static_cast(FPBits::inf()); + return x + FPBits::inf().get_val(); } } } diff --git a/libc/src/math/generic/log.cpp b/libc/src/math/generic/log.cpp index 2db6b7f48fd09..b0f7e8c9afa54 100644 --- a/libc/src/math/generic/log.cpp +++ b/libc/src/math/generic/log.cpp @@ -732,28 +732,29 @@ double log_accurate(int e_x, int index, double m_x) { LLVM_LIBC_FUNCTION(double, log, (double x)) { using FPBits_t = typename fputil::FPBits; + using Sign = fputil::Sign; FPBits_t xbits(x); uint64_t x_u = xbits.uintval(); int x_e = -FPBits_t::EXP_BIAS; - if (LIBC_UNLIKELY(x_u == 0x3FF0'0000'0000'0000ULL)) { + if (LIBC_UNLIKELY(xbits == FPBits_t::one())) { // log(1.0) = +0.0 return 0.0; } - if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::MIN_NORMAL || - xbits.uintval() > FPBits_t::MAX_NORMAL)) { + if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() || + xbits.uintval() > FPBits_t::max_normal().uintval())) { if (xbits.is_zero()) { // return -Inf and raise FE_DIVBYZERO. fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return static_cast(FPBits_t::inf(fputil::Sign::NEG)); + return FPBits_t::inf(Sign::NEG).get_val(); } if (xbits.is_neg() && !xbits.is_nan()) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits_t::build_quiet_nan(0); + return FPBits_t::build_quiet_nan().get_val(); } if (xbits.is_inf_or_nan()) { return x; diff --git a/libc/src/math/generic/log10.cpp b/libc/src/math/generic/log10.cpp index 3a4d321fdb18c..55a3fc5c061e5 100644 --- a/libc/src/math/generic/log10.cpp +++ b/libc/src/math/generic/log10.cpp @@ -733,28 +733,29 @@ double log10_accurate(int e_x, int index, double m_x) { LLVM_LIBC_FUNCTION(double, log10, (double x)) { using FPBits_t = typename fputil::FPBits; + using Sign = fputil::Sign; FPBits_t xbits(x); uint64_t x_u = xbits.uintval(); int x_e = -FPBits_t::EXP_BIAS; - if (LIBC_UNLIKELY(x_u == 0x3FF0'0000'0000'0000ULL)) { + if (LIBC_UNLIKELY(xbits == FPBits_t::one())) { // log10(1.0) = +0.0 return 0.0; } - if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::MIN_NORMAL || - xbits.uintval() > FPBits_t::MAX_NORMAL)) { + if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() || + xbits.uintval() > FPBits_t::max_normal().uintval())) { if (xbits.is_zero()) { // return -Inf and raise FE_DIVBYZERO. fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return static_cast(FPBits_t::inf(fputil::Sign::NEG)); + return FPBits_t::inf(Sign::NEG).get_val(); } if (xbits.is_neg() && !xbits.is_nan()) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits_t::build_quiet_nan(0); + return FPBits_t::build_quiet_nan().get_val(); } if (xbits.is_inf_or_nan()) { return x; diff --git a/libc/src/math/generic/log10f.cpp b/libc/src/math/generic/log10f.cpp index 46505f4e07e67..f87e34ec5fb38 100644 --- a/libc/src/math/generic/log10f.cpp +++ b/libc/src/math/generic/log10f.cpp @@ -106,6 +106,7 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) { constexpr double LOG10_2 = 0x1.34413509f79ffp-2; using FPBits = typename fputil::FPBits; + using Sign = fputil::Sign; FPBits xbits(x); uint32_t x_u = xbits.uintval(); @@ -160,18 +161,19 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) { int m = -FPBits::EXP_BIAS; - if (LIBC_UNLIKELY(x_u < FPBits::MIN_NORMAL || x_u > FPBits::MAX_NORMAL)) { + if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval() || + x_u > FPBits::max_normal().uintval())) { if (xbits.is_zero()) { // Return -inf and raise FE_DIVBYZERO fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return static_cast(FPBits::inf(fputil::Sign::NEG)); + return FPBits::inf(Sign::NEG).get_val(); } if (xbits.is_neg() && !xbits.is_nan()) { // Return NaN and raise FE_INVALID fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits::build_quiet_nan(0); + return FPBits::build_quiet_nan().get_val(); } if (xbits.is_inf_or_nan()) { return x; diff --git a/libc/src/math/generic/log1p.cpp b/libc/src/math/generic/log1p.cpp index 731fecae6f1b5..ae432620ba328 100644 --- a/libc/src/math/generic/log1p.cpp +++ b/libc/src/math/generic/log1p.cpp @@ -873,6 +873,7 @@ LIBC_INLINE double log1p_accurate(int e_x, int index, LLVM_LIBC_FUNCTION(double, log1p, (double x)) { using FPBits_t = typename fputil::FPBits; + using Sign = fputil::Sign; constexpr int EXP_BIAS = FPBits_t::EXP_BIAS; constexpr int FRACTION_LEN = FPBits_t::FRACTION_LEN; constexpr uint64_t FRACTION_MASK = FPBits_t::FRACTION_MASK; @@ -887,19 +888,19 @@ LLVM_LIBC_FUNCTION(double, log1p, (double x)) { // |x| >= 1 if (LIBC_UNLIKELY(x_u >= 0x4650'0000'0000'0000ULL)) { // x >= 2^102 or x is negative, inf, or NaN - if (LIBC_UNLIKELY(x_u > FPBits_t::MAX_NORMAL)) { + if (LIBC_UNLIKELY(x_u > FPBits_t::max_normal().uintval())) { // x <= -1.0 or x is Inf or NaN if (x_u == 0xbff0'0000'0000'0000ULL) { // x = -1.0 fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return static_cast(FPBits_t::inf(fputil::Sign::NEG)); + return FPBits_t::inf(Sign::NEG).get_val(); } if (xbits.is_neg() && !xbits.is_nan()) { // x < -1.0 fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits_t::build_quiet_nan(0); + return FPBits_t::build_quiet_nan().get_val(); } // x is +Inf or NaN return x; diff --git a/libc/src/math/generic/log1pf.cpp b/libc/src/math/generic/log1pf.cpp index 0812569c624b8..bc472caf54f89 100644 --- a/libc/src/math/generic/log1pf.cpp +++ b/libc/src/math/generic/log1pf.cpp @@ -43,11 +43,11 @@ LIBC_INLINE float log(double x) { uint64_t x_u = xbits.uintval(); - if (LIBC_UNLIKELY(x_u > FPBits::MAX_NORMAL)) { + if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) { if (xbits.is_neg() && !xbits.is_nan()) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return fputil::FPBits::build_quiet_nan(0); + return fputil::FPBits::build_quiet_nan().get_val(); } return static_cast(x); } diff --git a/libc/src/math/generic/log2.cpp b/libc/src/math/generic/log2.cpp index 5b7fb65d77385..480c690a65037 100644 --- a/libc/src/math/generic/log2.cpp +++ b/libc/src/math/generic/log2.cpp @@ -854,28 +854,29 @@ double log2_accurate(int e_x, int index, double m_x) { LLVM_LIBC_FUNCTION(double, log2, (double x)) { using FPBits_t = typename fputil::FPBits; + using Sign = fputil::Sign; FPBits_t xbits(x); uint64_t x_u = xbits.uintval(); int x_e = -FPBits_t::EXP_BIAS; - if (LIBC_UNLIKELY(x_u == 0x3FF0'0000'0000'0000ULL)) { + if (LIBC_UNLIKELY(xbits == FPBits_t::one())) { // log2(1.0) = +0.0 return 0.0; } - if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::MIN_NORMAL || - xbits.uintval() > FPBits_t::MAX_NORMAL)) { + if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() || + xbits.uintval() > FPBits_t::max_normal().uintval())) { if (xbits.is_zero()) { // return -Inf and raise FE_DIVBYZERO. fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return static_cast(FPBits_t::inf(fputil::Sign::NEG)); + return FPBits_t::inf(Sign::NEG).get_val(); } if (xbits.is_neg() && !xbits.is_nan()) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits_t::build_quiet_nan(0); + return FPBits_t::build_quiet_nan().get_val(); } if (xbits.is_inf_or_nan()) { return x; diff --git a/libc/src/math/generic/log2f.cpp b/libc/src/math/generic/log2f.cpp index 9cddbb9e8ea48..7eaa5d53ccedd 100644 --- a/libc/src/math/generic/log2f.cpp +++ b/libc/src/math/generic/log2f.cpp @@ -55,6 +55,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, log2f, (float x)) { using FPBits = typename fputil::FPBits; + using Sign = fputil::Sign; FPBits xbits(x); uint32_t x_u = xbits.uintval(); @@ -68,16 +69,17 @@ LLVM_LIBC_FUNCTION(float, log2f, (float x)) { return 0.0f; // Exceptional inputs. - if (LIBC_UNLIKELY(x_u < FPBits::MIN_NORMAL || x_u > FPBits::MAX_NORMAL)) { + if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval() || + x_u > FPBits::max_normal().uintval())) { if (xbits.is_zero()) { fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return static_cast(FPBits::inf(fputil::Sign::NEG)); + return FPBits::inf(Sign::NEG).get_val(); } if (xbits.is_neg() && !xbits.is_nan()) { fputil::set_errno_if_required(EDOM); fputil::raise_except(FE_INVALID); - return FPBits::build_quiet_nan(0); + return FPBits::build_quiet_nan().get_val(); } if (xbits.is_inf_or_nan()) { return x; diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp index 8ccb55dcc9e33..88f7ea01b2f19 100644 --- a/libc/src/math/generic/logf.cpp +++ b/libc/src/math/generic/logf.cpp @@ -54,6 +54,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, logf, (float x)) { constexpr double LOG_2 = 0x1.62e42fefa39efp-1; using FPBits = typename fputil::FPBits; + using Sign = fputil::Sign; FPBits xbits(x); uint32_t x_u = xbits.uintval(); @@ -79,7 +80,7 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) { #endif // LIBC_TARGET_CPU_HAS_FMA } // Subnormal inputs. - if (LIBC_UNLIKELY(x_u < FPBits::MIN_NORMAL)) { + if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) { if (x_u == 0) { // Return -inf and raise FE_DIVBYZERO fputil::set_errno_if_required(ERANGE); @@ -112,18 +113,18 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) { #endif // LIBC_TARGET_CPU_HAS_FMA } // Exceptional inputs. - if (LIBC_UNLIKELY(x_u > FPBits::MAX_NORMAL)) { + if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) { if (x_u == 0x8000'0000U) { // Return -inf and raise FE_DIVBYZERO fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return static_cast(FPBits::inf(fputil::Sign::NEG)); + return FPBits::inf(Sign::NEG).get_val(); } if (xbits.is_neg() && !xbits.is_nan()) { // Return NaN and raise FE_INVALID fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FPBits::build_quiet_nan(0); + return FPBits::build_quiet_nan().get_val(); } // x is +inf or nan return x; diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp index 932f1d70c33e8..0e164ab8b4225 100644 --- a/libc/src/math/generic/powf.cpp +++ b/libc/src/math/generic/powf.cpp @@ -547,14 +547,15 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) { // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_DIVBYZERO); - return FloatBits::inf(); + return FloatBits::inf().get_val(); } // pow (|x| < 1, -inf) = +inf // pow (|x| < 1, +inf) = 0.0f // pow (|x| > 1, -inf) = 0.0f // pow (|x| > 1, +inf) = +inf - return ((x_abs < 0x3f80'0000) == (y_u == 0xff80'0000)) ? FloatBits::inf() - : 0.0f; + return ((x_abs < 0x3f80'0000) == (y_u == 0xff80'0000)) + ? FloatBits::inf().get_val() + : 0.0f; } default: // Speed up for common exponents @@ -617,7 +618,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) { // pow(0, negative number) = inf fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_DIVBYZERO); - return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS); + return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS).get_val(); } // pow(0, positive number) = 0 return out_is_neg ? -0.0f : 0.0f; @@ -628,7 +629,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) { if (y_u >= FloatBits::SIGN_MASK) { return out_is_neg ? -0.0f : 0.0f; } - return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS); + return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS).get_val(); } } @@ -656,7 +657,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) { // pow( negative, non-integer ) = NaN fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); - return FloatBits::build_quiet_nan(0); + return FloatBits::build_quiet_nan().get_val(); } } } diff --git a/libc/src/math/generic/sincosf.cpp b/libc/src/math/generic/sincosf.cpp index 44371db710871..f12b93a0e6965 100644 --- a/libc/src/math/generic/sincosf.cpp +++ b/libc/src/math/generic/sincosf.cpp @@ -148,7 +148,9 @@ LLVM_LIBC_FUNCTION(void, sincosf, (float x, float *sinp, float *cosp)) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); } - *sinp = x + FPBits::build_nan(FPBits::FRACTION_MASK); + *sinp = + x + + FPBits::build_nan(fputil::Sign::POS, FPBits::FRACTION_MASK).get_val(); *cosp = *sinp; return; } diff --git a/libc/src/math/generic/sinf.cpp b/libc/src/math/generic/sinf.cpp index 9e574d4e57240..7ba479f0a4598 100644 --- a/libc/src/math/generic/sinf.cpp +++ b/libc/src/math/generic/sinf.cpp @@ -139,7 +139,7 @@ LLVM_LIBC_FUNCTION(float, sinf, (float x)) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); } - return x + FPBits::build_quiet_nan(0); + return x + FPBits::build_quiet_nan().get_val(); } // Combine the results with the sine of sum formula: diff --git a/libc/src/math/generic/sinhf.cpp b/libc/src/math/generic/sinhf.cpp index b3850c6742706..780c9a1f8d6ac 100644 --- a/libc/src/math/generic/sinhf.cpp +++ b/libc/src/math/generic/sinhf.cpp @@ -56,16 +56,16 @@ LLVM_LIBC_FUNCTION(float, sinhf, (float x)) { int rounding = fputil::quick_get_round(); if (xbits.is_neg()) { if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO)) - return -FPBits::max_normal(); + return -FPBits::max_normal().get_val(); } else { if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)) - return FPBits::max_normal(); + return FPBits::max_normal().get_val(); } fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_OVERFLOW); - return x + FPBits::inf(xbits.sign()); + return x + FPBits::inf(xbits.sign()).get_val(); } // sinh(x) = (e^x - e^(-x)) / 2. diff --git a/libc/src/math/generic/tanf.cpp b/libc/src/math/generic/tanf.cpp index 7909e9e5d5568..09dd62eae03f8 100644 --- a/libc/src/math/generic/tanf.cpp +++ b/libc/src/math/generic/tanf.cpp @@ -114,7 +114,7 @@ LLVM_LIBC_FUNCTION(float, tanf, (float x)) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); } - return x + FPBits::build_quiet_nan(0); + return x + FPBits::build_quiet_nan().get_val(); } // Other large exceptional values if (auto r = TANF_EXCEPTS.lookup_odd(x_abs, x_sign); diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h index 26b8e3e60bdfd..9880fa51c5481 100644 --- a/libc/test/UnitTest/FPMatcher.h +++ b/libc/test/UnitTest/FPMatcher.h @@ -66,16 +66,16 @@ template struct FPTest : public Test { using Sign = LIBC_NAMESPACE::fputil::Sign; static constexpr StorageType STORAGE_MAX = LIBC_NAMESPACE::cpp::numeric_limits::max(); - static constexpr T zero = FPBits::zero(Sign::POS); - static constexpr T neg_zero = FPBits::zero(Sign::NEG); - static constexpr T aNaN = FPBits::build_quiet_nan(1); - static constexpr T sNaN = FPBits::build_nan(1); - static constexpr T inf = FPBits::inf(Sign::POS); - static constexpr T neg_inf = FPBits::inf(Sign::NEG); - static constexpr T min_normal = FPBits::min_normal(); - static constexpr T max_normal = FPBits::max_normal(); - static constexpr T min_denormal = FPBits::min_denormal(); - static constexpr T max_denormal = FPBits::max_denormal(); + static constexpr T zero = T(FPBits::zero(Sign::POS)); + static constexpr T neg_zero = T(FPBits::zero(Sign::NEG)); + static constexpr T aNaN = T(FPBits::build_quiet_nan(Sign::POS, 1)); + static constexpr T sNaN = T(FPBits::build_nan(Sign::POS, 1)); + static constexpr T inf = T(FPBits::inf(Sign::POS)); + static constexpr T neg_inf = T(FPBits::inf(Sign::NEG)); + static constexpr T min_normal = T(FPBits::min_normal()); + static constexpr T max_normal = T(FPBits::max_normal()); + static constexpr T min_denormal = T(FPBits::min_subnormal()); + static constexpr T max_denormal = T(FPBits::max_subnormal()); static constexpr int N_ROUNDING_MODES = 4; static constexpr fputil::testing::RoundingMode ROUNDING_MODES[4] = { @@ -95,16 +95,16 @@ template struct FPTest : public Test { using Sign = LIBC_NAMESPACE::fputil::Sign; \ static constexpr StorageType STORAGE_MAX = \ LIBC_NAMESPACE::cpp::numeric_limits::max(); \ - const T zero = FPBits::zero(Sign::POS); \ - const T neg_zero = FPBits::zero(Sign::NEG); \ - const T aNaN = FPBits::build_quiet_nan(1); \ - const T sNaN = FPBits::build_nan(1); \ - const T inf = FPBits::inf(Sign::POS); \ - const T neg_inf = FPBits::inf(Sign::NEG); \ - const T min_normal = FPBits::min_normal(); \ - const T max_normal = FPBits::max_normal(); \ - const T min_denormal = FPBits::min_denormal(); \ - const T max_denormal = FPBits::max_denormal(); + const T zero = T(FPBits::zero(Sign::POS)); \ + const T neg_zero = T(FPBits::zero(Sign::NEG)); \ + const T aNaN = T(FPBits::build_quiet_nan(Sign::POS, 1)); \ + const T sNaN = T(FPBits::build_nan(Sign::POS, 1)); \ + const T inf = T(FPBits::inf(Sign::POS)); \ + const T neg_inf = T(FPBits::inf(Sign::NEG)); \ + const T min_normal = T(FPBits::min_normal()); \ + const T max_normal = T(FPBits::max_normal()); \ + const T min_denormal = T(FPBits::min_subnormal()); \ + const T max_denormal = T(FPBits::max_subnormal()); #define EXPECT_FP_EQ(expected, actual) \ EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcher< \ diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp index e6b6d7d9ec780..6092945811ce1 100644 --- a/libc/test/src/__support/FPUtil/fpbits_test.cpp +++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp @@ -232,13 +232,11 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) { TEST(LlvmLibcFPBitsTest, FloatType) { using FloatBits = FPBits; - EXPECT_STREQ( - LIBC_NAMESPACE::str(FloatBits(FloatBits::inf(Sign::POS))).c_str(), - "(+Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(FloatBits(FloatBits::inf(Sign::NEG))).c_str(), - "(-Infinity)"); - EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits(FloatBits::build_nan(1))).c_str(), + EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::inf(Sign::POS)).c_str(), + "(+Infinity)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::inf(Sign::NEG)).c_str(), + "(-Infinity)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(FloatBits::build_nan(Sign::POS, 1)).c_str(), "(NaN)"); FloatBits zero(0.0f); @@ -289,22 +287,19 @@ TEST(LlvmLibcFPBitsTest, FloatType) { EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), "0xBF900000 = (S: 1, E: 0x007F, M: 0x00100000)"); - FloatBits quiet_nan = FloatBits(FloatBits::build_quiet_nan(1)); + FloatBits quiet_nan = FloatBits::build_quiet_nan(Sign::POS, 1); EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } TEST(LlvmLibcFPBitsTest, DoubleType) { using DoubleBits = FPBits; - EXPECT_STREQ( - LIBC_NAMESPACE::str(DoubleBits(DoubleBits::inf(Sign::POS))).c_str(), - "(+Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(DoubleBits(DoubleBits::inf(Sign::NEG))).c_str(), - "(-Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(DoubleBits(DoubleBits::build_nan(1))).c_str(), - "(NaN)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::inf(Sign::POS)).c_str(), + "(+Infinity)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::inf(Sign::NEG)).c_str(), + "(-Infinity)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(DoubleBits::build_nan(Sign::POS, 1)).c_str(), + "(NaN)"); DoubleBits zero(0.0); EXPECT_TRUE(zero.is_pos()); @@ -354,7 +349,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) { EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), "0xBFF2000000000000 = (S: 1, E: 0x03FF, M: 0x0002000000000000)"); - DoubleBits quiet_nan = DoubleBits(DoubleBits::build_quiet_nan(1)); + DoubleBits quiet_nan = DoubleBits::build_quiet_nan(Sign::POS, 1); EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } @@ -365,16 +360,12 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) { if constexpr (sizeof(long double) == sizeof(double)) return; // The tests for the "double" type cover for this case. + EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(), + "(+Infinity)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::NEG)).c_str(), + "(-Infinity)"); EXPECT_STREQ( - LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::POS))) - .c_str(), - "(+Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::NEG))) - .c_str(), - "(-Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::build_nan(1))).c_str(), + LIBC_NAMESPACE::str(LongDoubleBits::build_nan(Sign::POS, 1)).c_str(), "(NaN)"); LongDoubleBits zero(0.0l); @@ -440,7 +431,7 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) { "0x000000000000BFFF9000000000000000 = " "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)"); - LongDoubleBits quiet_nan = LongDoubleBits(LongDoubleBits::build_quiet_nan(1)); + LongDoubleBits quiet_nan = LongDoubleBits::build_quiet_nan(Sign::POS, 1); EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } #else @@ -450,16 +441,12 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) { #else using LongDoubleBits = FPBits; + EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(), + "(+Infinity)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::NEG)).c_str(), + "(-Infinity)"); EXPECT_STREQ( - LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::POS))) - .c_str(), - "(+Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::inf(Sign::NEG))) - .c_str(), - "(-Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(LongDoubleBits(LongDoubleBits::build_nan(1))).c_str(), + LIBC_NAMESPACE::str(LongDoubleBits::build_nan(Sign::POS, 1)).c_str(), "(NaN)"); LongDoubleBits zero(0.0l); @@ -519,7 +506,7 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) { "0xBFFF2000000000000000000000000000 = " "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)"); - LongDoubleBits quiet_nan = LongDoubleBits(LongDoubleBits::build_quiet_nan(1)); + LongDoubleBits quiet_nan = LongDoubleBits::build_quiet_nan(Sign::POS, 1); EXPECT_EQ(quiet_nan.is_quiet_nan(), true); #endif } @@ -529,17 +516,15 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) { TEST(LlvmLibcFPBitsTest, Float128Type) { using Float128Bits = FPBits; + EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits::inf(Sign::POS)).c_str(), + "(+Infinity)"); + EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits::inf(Sign::NEG)).c_str(), + "(-Infinity)"); EXPECT_STREQ( - LIBC_NAMESPACE::str(Float128Bits(Float128Bits::inf(Sign::POS))).c_str(), - "(+Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(Float128Bits(Float128Bits::inf(Sign::NEG))).c_str(), - "(-Infinity)"); - EXPECT_STREQ( - LIBC_NAMESPACE::str(Float128Bits(Float128Bits::build_nan(1))).c_str(), + LIBC_NAMESPACE::str(Float128Bits::build_nan(Sign::POS, 1)).c_str(), "(NaN)"); - Float128Bits zero(Float128Bits::zero()); + Float128Bits zero = Float128Bits::zero(Sign::POS); EXPECT_TRUE(zero.is_pos()); EXPECT_EQ(zero.get_biased_exponent(), static_cast(0x0000)); EXPECT_EQ(zero.get_mantissa(), static_cast(0x0000000000000000) @@ -549,7 +534,7 @@ TEST(LlvmLibcFPBitsTest, Float128Type) { "0x00000000000000000000000000000000 = " "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)"); - Float128Bits negzero(Float128Bits::zero(Sign::NEG)); + Float128Bits negzero = Float128Bits::zero(Sign::NEG); EXPECT_TRUE(negzero.is_neg()); EXPECT_EQ(negzero.get_biased_exponent(), static_cast(0x0000)); EXPECT_EQ(negzero.get_mantissa(), static_cast(0x0000000000000000) @@ -596,7 +581,7 @@ TEST(LlvmLibcFPBitsTest, Float128Type) { "0xBFFF2000000000000000000000000000 = " "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)"); - Float128Bits quiet_nan = Float128Bits(Float128Bits::build_quiet_nan(1)); + Float128Bits quiet_nan = Float128Bits::build_quiet_nan(Sign::POS, 1); EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } #endif // LIBC_COMPILER_HAS_FLOAT128 diff --git a/libc/test/src/math/FDimTest.h b/libc/test/src/math/FDimTest.h index 0744e6ea8fd8f..c3d9cb1801cd4 100644 --- a/libc/test/src/math/FDimTest.h +++ b/libc/test/src/math/FDimTest.h @@ -24,7 +24,7 @@ class FDimTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); void test_na_n_arg(FuncPtr func) { EXPECT_FP_EQ(nan, func(nan, inf)); diff --git a/libc/test/src/math/FmaTest.h b/libc/test/src/math/FmaTest.h index 032a79821d590..4343b38053dc4 100644 --- a/libc/test/src/math/FmaTest.h +++ b/libc/test/src/math/FmaTest.h @@ -25,11 +25,21 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test { using StorageType = typename FPBits::StorageType; using Sign = LIBC_NAMESPACE::fputil::Sign; + const T min_subnormal = T(FPBits::min_subnormal(Sign::POS)); + const T min_normal = T(FPBits::min_normal(Sign::POS)); + const T max_normal = T(FPBits::max_normal(Sign::POS)); const T inf = T(FPBits::inf(Sign::POS)); const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); + + static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); + static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + static constexpr StorageType MAX_SUBNORMAL = + FPBits::max_subnormal().uintval(); + static constexpr StorageType MIN_SUBNORMAL = + FPBits::min_subnormal().uintval(); StorageType get_random_bit_pattern() { StorageType bits{0}; @@ -52,14 +62,13 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test { EXPECT_FP_EQ(func(inf, neg_inf, nan), nan); // Test underflow rounding up. - EXPECT_FP_EQ(func(T(0.5), FPBits::min_denormal(), FPBits::min_denormal()), + EXPECT_FP_EQ(func(T(0.5), min_subnormal, min_subnormal), T(FPBits(StorageType(2)))); // Test underflow rounding down. - T v = T(FPBits(FPBits::MIN_NORMAL + StorageType(1))); - EXPECT_FP_EQ( - func(T(1) / T(FPBits::MIN_NORMAL << 1), v, FPBits::min_normal()), v); + T v = T(FPBits(MIN_NORMAL + StorageType(1))); + EXPECT_FP_EQ(func(T(1) / T(MIN_NORMAL << 1), v, min_normal), v); // Test overflow. - T z = FPBits::max_normal(); + T z = max_normal; EXPECT_FP_EQ(func(T(1.75), z, -z), T(0.75) * z); // Exact cancellation. EXPECT_FP_EQ(func(T(3.0), T(5.0), -T(15.0)), T(0.0)); @@ -68,11 +77,9 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test { void test_subnormal_range(Func func) { constexpr StorageType COUNT = 100'001; - constexpr StorageType STEP = - (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; - for (StorageType v = FPBits::MIN_SUBNORMAL, w = FPBits::MAX_SUBNORMAL; - v <= FPBits::MAX_SUBNORMAL && w >= FPBits::MIN_SUBNORMAL; - v += STEP, w -= STEP) { + constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; + for (StorageType v = MIN_SUBNORMAL, w = MAX_SUBNORMAL; + v <= MAX_SUBNORMAL && w >= MIN_SUBNORMAL; v += STEP, w -= STEP) { T x = T(FPBits(get_random_bit_pattern())), y = T(FPBits(v)), z = T(FPBits(w)); mpfr::TernaryInput input{x, y, z}; @@ -83,11 +90,9 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test { void test_normal_range(Func func) { constexpr StorageType COUNT = 100'001; - constexpr StorageType STEP = - (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT; - for (StorageType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL; - v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL; - v += STEP, w -= STEP) { + constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; + for (StorageType v = MIN_NORMAL, w = MAX_NORMAL; + v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) { T x = T(FPBits(v)), y = T(FPBits(w)), z = T(FPBits(get_random_bit_pattern())); mpfr::TernaryInput input{x, y, z}; diff --git a/libc/test/src/math/HypotTest.h b/libc/test/src/math/HypotTest.h index b7eb63c192c70..0b85f68fda82a 100644 --- a/libc/test/src/math/HypotTest.h +++ b/libc/test/src/math/HypotTest.h @@ -25,15 +25,22 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using Sign = LIBC_NAMESPACE::fputil::Sign; using StorageType = typename FPBits::StorageType; - const T nan = FPBits::build_quiet_nan(1); - const T inf = FPBits::inf(); - const T neg_inf = FPBits::inf(Sign::NEG); - const T zero = FPBits::zero(); - const T neg_zero = FPBits::zero(Sign::NEG); - const T max_normal = FPBits::max_normal(); - const T min_normal = FPBits::min_normal(); - const T max_subnormal = FPBits::max_denormal(); - const T min_subnormal = FPBits::min_denormal(); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); + const T inf = T(FPBits::inf()); + const T neg_inf = T(FPBits::inf(Sign::NEG)); + const T zero = T(FPBits::zero()); + const T neg_zero = T(FPBits::zero(Sign::NEG)); + const T max_normal = T(FPBits::max_normal()); + const T min_normal = T(FPBits::min_normal()); + const T max_subnormal = T(FPBits::max_subnormal()); + const T min_subnormal = T(FPBits::min_subnormal()); + + static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); + static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + static constexpr StorageType MAX_SUBNORMAL = + FPBits::max_subnormal().uintval(); + static constexpr StorageType MIN_SUBNORMAL = + FPBits::min_subnormal().uintval(); public: void test_special_numbers(Func func) { @@ -62,12 +69,11 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test { void test_subnormal_range(Func func) { constexpr StorageType COUNT = 10'001; for (unsigned scale = 0; scale < 4; ++scale) { - StorageType max_value = FPBits::MAX_SUBNORMAL << scale; - StorageType step = (max_value - FPBits::MIN_SUBNORMAL) / COUNT; + StorageType max_value = MAX_SUBNORMAL << scale; + StorageType step = (max_value - MIN_SUBNORMAL) / COUNT; for (int signs = 0; signs < 4; ++signs) { - for (StorageType v = FPBits::MIN_SUBNORMAL, w = max_value; - v <= max_value && w >= FPBits::MIN_SUBNORMAL; - v += step, w -= step) { + for (StorageType v = MIN_SUBNORMAL, w = max_value; + v <= max_value && w >= MIN_SUBNORMAL; v += step, w -= step) { T x = T(FPBits(v)), y = T(FPBits(w)); if (signs % 2 == 1) { x = -x; @@ -86,13 +92,10 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test { void test_normal_range(Func func) { constexpr StorageType COUNT = 10'001; - constexpr StorageType STEP = - (StorageType(FPBits::MAX_NORMAL) - StorageType(FPBits::MIN_NORMAL)) / - COUNT; + constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; for (int signs = 0; signs < 4; ++signs) { - for (StorageType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL; - v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL; - v += STEP, w -= STEP) { + for (StorageType v = MIN_NORMAL, w = MAX_NORMAL; + v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) { T x = T(FPBits(v)), y = T(FPBits(w)); if (signs % 2 == 1) { x = -x; diff --git a/libc/test/src/math/ILogbTest.h b/libc/test/src/math/ILogbTest.h index 9fa25c9ff9861..223de789999af 100644 --- a/libc/test/src/math/ILogbTest.h +++ b/libc/test/src/math/ILogbTest.h @@ -26,10 +26,10 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { void test_special_numbers(typename ILogbFunc::Func func) { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using Sign = LIBC_NAMESPACE::fputil::Sign; - EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero()))); + EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::POS)))); EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::NEG)))); - EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(1)))); - EXPECT_EQ(INT_MAX, func(T(FPBits::inf()))); + EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(Sign::POS, 1)))); + EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::POS)))); EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::NEG)))); } @@ -76,11 +76,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { void test_subnormal_range(typename ILogbFunc::Func func) { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using StorageType = typename FPBits::StorageType; + constexpr StorageType MIN_SUBNORMAL = FPBits::min_subnormal().uintval(); + constexpr StorageType MAX_SUBNORMAL = FPBits::max_subnormal().uintval(); constexpr StorageType COUNT = 10'001; - constexpr StorageType STEP = - (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; - for (StorageType v = FPBits::MIN_SUBNORMAL; v <= FPBits::MAX_SUBNORMAL; - v += STEP) { + constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; + for (StorageType v = MIN_SUBNORMAL; v <= MAX_SUBNORMAL; v += STEP) { T x = T(FPBits(v)); if (isnan(x) || isinf(x) || x == 0.0) continue; @@ -95,11 +95,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { void test_normal_range(typename ILogbFunc::Func func) { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using StorageType = typename FPBits::StorageType; + constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); constexpr StorageType COUNT = 10'001; - constexpr StorageType STEP = - (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT; - for (StorageType v = FPBits::MIN_NORMAL; v <= FPBits::MAX_NORMAL; - v += STEP) { + constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; + for (StorageType v = MIN_NORMAL; v <= MAX_NORMAL; v += STEP) { T x = T(FPBits(v)); if (isnan(x) || isinf(x) || x == 0.0) continue; diff --git a/libc/test/src/math/LdExpTest.h b/libc/test/src/math/LdExpTest.h index 25120ba3646fd..3a4baabbf10e6 100644 --- a/libc/test/src/math/LdExpTest.h +++ b/libc/test/src/math/LdExpTest.h @@ -29,7 +29,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); // A normalized mantissa to be used with tests. static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x1234; diff --git a/libc/test/src/math/NextAfterTest.h b/libc/test/src/math/NextAfterTest.h index aa9646fd921f8..9ff3bf73d2ede 100644 --- a/libc/test/src/math/NextAfterTest.h +++ b/libc/test/src/math/NextAfterTest.h @@ -27,12 +27,12 @@ class NextAfterTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); - const StorageType min_subnormal = FPBits::MIN_SUBNORMAL; - const StorageType max_subnormal = FPBits::MAX_SUBNORMAL; - const StorageType min_normal = FPBits::MIN_NORMAL; - const StorageType max_normal = FPBits::MAX_NORMAL; + const StorageType min_subnormal = FPBits::min_subnormal().uintval(); + const StorageType max_subnormal = FPBits::max_subnormal().uintval(); + const StorageType min_normal = FPBits::min_normal().uintval(); + const StorageType max_normal = FPBits::max_normal().uintval(); public: typedef T (*NextAfterFunc)(T, T); diff --git a/libc/test/src/math/RIntTest.h b/libc/test/src/math/RIntTest.h index 6816e94d389f4..b478e3f65dbc8 100644 --- a/libc/test/src/math/RIntTest.h +++ b/libc/test/src/math/RIntTest.h @@ -38,7 +38,14 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); + + static constexpr StorageType MIN_SUBNORMAL = + FPBits::min_subnormal().uintval(); + static constexpr StorageType MAX_SUBNORMAL = + FPBits::max_subnormal().uintval(); + static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); static inline mpfr::RoundingMode to_mpfr_rounding_mode(int mode) { switch (mode) { @@ -95,10 +102,8 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test { void testSubnormalRange(RIntFunc func) { constexpr StorageType COUNT = 100'001; - constexpr StorageType STEP = - (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; - for (StorageType i = FPBits::MIN_SUBNORMAL; i <= FPBits::MAX_SUBNORMAL; - i += STEP) { + constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; + for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) { T x = T(FPBits(i)); for (int mode : ROUNDING_MODES) { LIBC_NAMESPACE::fputil::set_round(mode); @@ -110,10 +115,8 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test { void testNormalRange(RIntFunc func) { constexpr StorageType COUNT = 100'001; - constexpr StorageType STEP = - (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT; - for (StorageType i = FPBits::MIN_NORMAL; i <= FPBits::MAX_NORMAL; - i += STEP) { + constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; + for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) { T x = T(FPBits(i)); // In normal range on x86 platforms, the long double implicit 1 bit can be // zero making the numbers NaN. We will skip them. diff --git a/libc/test/src/math/RemQuoTest.h b/libc/test/src/math/RemQuoTest.h index 9ed9525662452..0ee41f4bf9acf 100644 --- a/libc/test/src/math/RemQuoTest.h +++ b/libc/test/src/math/RemQuoTest.h @@ -28,7 +28,14 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); + + static constexpr StorageType MIN_SUBNORMAL = + FPBits::min_subnormal().uintval(); + static constexpr StorageType MAX_SUBNORMAL = + FPBits::max_subnormal().uintval(); + static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); public: typedef T (*RemQuoFunc)(T, T, int *); @@ -97,11 +104,9 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test { void testSubnormalRange(RemQuoFunc func) { constexpr StorageType COUNT = 100'001; - constexpr StorageType STEP = - (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; - for (StorageType v = FPBits::MIN_SUBNORMAL, w = FPBits::MAX_SUBNORMAL; - v <= FPBits::MAX_SUBNORMAL && w >= FPBits::MIN_SUBNORMAL; - v += STEP, w -= STEP) { + constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; + for (StorageType v = MIN_SUBNORMAL, w = MAX_SUBNORMAL; + v <= MAX_SUBNORMAL && w >= MIN_SUBNORMAL; v += STEP, w -= STEP) { T x = T(FPBits(v)), y = T(FPBits(w)); mpfr::BinaryOutput result; mpfr::BinaryInput input{x, y}; @@ -112,11 +117,9 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test { void testNormalRange(RemQuoFunc func) { constexpr StorageType COUNT = 1'001; - constexpr StorageType STEP = - (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT; - for (StorageType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL; - v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL; - v += STEP, w -= STEP) { + constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; + for (StorageType v = MIN_NORMAL, w = MAX_NORMAL; + v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) { T x = T(FPBits(v)), y = T(FPBits(w)); mpfr::BinaryOutput result; mpfr::BinaryInput input{x, y}; diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h index e8ada1b4c36c5..6866c23cb99ca 100644 --- a/libc/test/src/math/RoundToIntegerTest.h +++ b/libc/test/src/math/RoundToIntegerTest.h @@ -37,7 +37,15 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test { const F neg_zero = F(FPBits::zero(Sign::NEG)); const F inf = F(FPBits::inf()); const F neg_inf = F(FPBits::inf(Sign::NEG)); - const F nan = F(FPBits::build_quiet_nan(1)); + const F nan = F(FPBits::build_quiet_nan(Sign::POS, 1)); + + static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); + static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + static constexpr StorageType MAX_SUBNORMAL = + FPBits::max_subnormal().uintval(); + static constexpr StorageType MIN_SUBNORMAL = + FPBits::min_subnormal().uintval(); + static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1); static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1); @@ -215,10 +223,8 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test { void testSubnormalRange(RoundToIntegerFunc func) { constexpr StorageType COUNT = 1'000'001; - constexpr StorageType STEP = - (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; - for (StorageType i = FPBits::MIN_SUBNORMAL; i <= FPBits::MAX_SUBNORMAL; - i += STEP) { + constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; + for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) { F x = F(FPBits(i)); if (x == F(0.0)) continue; @@ -259,10 +265,8 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test { return; constexpr StorageType COUNT = 1'000'001; - constexpr StorageType STEP = - (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT; - for (StorageType i = FPBits::MIN_NORMAL; i <= FPBits::MAX_NORMAL; - i += STEP) { + constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; + for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) { F x = F(FPBits(i)); // In normal range on x86 platforms, the long double implicit 1 bit can be // zero making the numbers NaN. We will skip them. diff --git a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h b/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h index ada7c9e495426..48572e78e5153 100644 --- a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h +++ b/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h @@ -109,10 +109,13 @@ template class BinaryOpSingleOutputDiff { std::ofstream log(logFile); log << " Performance tests with inputs in denormal range:\n"; run_perf_in_range(myFunc, otherFunc, /* startingBit= */ StorageType(0), - /* endingBit= */ FPBits::MAX_SUBNORMAL, 1'000'001, log); + /* endingBit= */ FPBits::max_subnormal().uintval(), + 1'000'001, log); log << "\n Performance tests with inputs in normal range:\n"; - run_perf_in_range(myFunc, otherFunc, /* startingBit= */ FPBits::MIN_NORMAL, - /* endingBit= */ FPBits::MAX_NORMAL, 100'000'001, log); + run_perf_in_range(myFunc, otherFunc, + /* startingBit= */ FPBits::min_normal().uintval(), + /* endingBit= */ FPBits::max_normal().uintval(), + 100'000'001, log); log << "\n Performance tests with inputs in normal range with exponents " "close to each other:\n"; run_perf_in_range( @@ -126,11 +129,12 @@ template class BinaryOpSingleOutputDiff { log << " Diff tests with inputs in denormal range:\n"; diffCount += run_diff_in_range( myFunc, otherFunc, /* startingBit= */ StorageType(0), - /* endingBit= */ FPBits::MAX_SUBNORMAL, 1'000'001, log); + /* endingBit= */ FPBits::max_subnormal().uintval(), 1'000'001, log); log << "\n Diff tests with inputs in normal range:\n"; diffCount += run_diff_in_range( - myFunc, otherFunc, /* startingBit= */ FPBits::MIN_NORMAL, - /* endingBit= */ FPBits::MAX_NORMAL, 100'000'001, log); + myFunc, otherFunc, + /* startingBit= */ FPBits::min_normal().uintval(), + /* endingBit= */ FPBits::max_normal().uintval(), 100'000'001, log); log << "\n Diff tests with inputs in normal range with exponents " "close to each other:\n"; diffCount += run_diff_in_range( diff --git a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h b/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h index e4cd06eb22b71..5e8310e889dc6 100644 --- a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h +++ b/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h @@ -93,10 +93,11 @@ template class SingleInputSingleOutputDiff { std::ofstream log(logFile); log << " Performance tests with inputs in denormal range:\n"; runPerfInRange(myFunc, otherFunc, /* startingBit= */ StorageType(0), - /* endingBit= */ FPBits::MAX_SUBNORMAL, log); + /* endingBit= */ FPBits::max_subnormal().uintval(), log); log << "\n Performance tests with inputs in normal range:\n"; - runPerfInRange(myFunc, otherFunc, /* startingBit= */ FPBits::MIN_NORMAL, - /* endingBit= */ FPBits::MAX_NORMAL, log); + runPerfInRange(myFunc, otherFunc, + /* startingBit= */ FPBits::min_normal().uintval(), + /* endingBit= */ FPBits::max_normal().uintval(), log); } }; diff --git a/libc/test/src/math/smoke/FDimTest.h b/libc/test/src/math/smoke/FDimTest.h index 0744e6ea8fd8f..c3d9cb1801cd4 100644 --- a/libc/test/src/math/smoke/FDimTest.h +++ b/libc/test/src/math/smoke/FDimTest.h @@ -24,7 +24,7 @@ class FDimTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); void test_na_n_arg(FuncPtr func) { EXPECT_FP_EQ(nan, func(nan, inf)); diff --git a/libc/test/src/math/smoke/FmaTest.h b/libc/test/src/math/smoke/FmaTest.h index dc624d871b990..337ce659a23e1 100644 --- a/libc/test/src/math/smoke/FmaTest.h +++ b/libc/test/src/math/smoke/FmaTest.h @@ -25,7 +25,7 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); public: void test_special_numbers(Func func) { @@ -39,14 +39,16 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test { EXPECT_FP_EQ(func(inf, neg_inf, nan), nan); // Test underflow rounding up. - EXPECT_FP_EQ(func(T(0.5), FPBits::min_denormal(), FPBits::min_denormal()), - T(FPBits(StorageType(2)))); - // Test underflow rounding down. - T v = T(FPBits(FPBits::MIN_NORMAL + StorageType(1))); EXPECT_FP_EQ( - func(T(1) / T(FPBits::MIN_NORMAL << 1), v, FPBits::min_normal()), v); + func(T(0.5), T(FPBits::min_subnormal()), T(FPBits::min_subnormal())), + T(FPBits(StorageType(2)))); + // Test underflow rounding down. + StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + T v = T(FPBits(MIN_NORMAL + StorageType(1))); + EXPECT_FP_EQ(func(T(1) / T(MIN_NORMAL << 1), v, T(FPBits::min_normal())), + v); // Test overflow. - T z = FPBits::max_normal(); + T z = T(FPBits::max_normal()); EXPECT_FP_EQ(func(T(1.75), z, -z), T(0.75) * z); // Exact cancellation. EXPECT_FP_EQ(func(T(3.0), T(5.0), -T(15.0)), T(0.0)); diff --git a/libc/test/src/math/smoke/HypotTest.h b/libc/test/src/math/smoke/HypotTest.h index 77454c19a6538..67110536b9623 100644 --- a/libc/test/src/math/smoke/HypotTest.h +++ b/libc/test/src/math/smoke/HypotTest.h @@ -22,16 +22,16 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using StorageType = typename FPBits::StorageType; using Sign = LIBC_NAMESPACE::fputil::Sign; - const T nan = FPBits::build_quiet_nan(1); - const T inf = FPBits::inf(Sign::POS); - const T neg_inf = FPBits::inf(Sign::NEG); - const T zero = FPBits::zero(Sign::POS); - const T neg_zero = FPBits::zero(Sign::NEG); - - const T max_normal = FPBits::max_normal(); - const T min_normal = FPBits::min_normal(); - const T max_subnormal = FPBits::max_denormal(); - const T min_subnormal = FPBits::min_denormal(); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); + const T inf = T(FPBits::inf(Sign::POS)); + const T neg_inf = T(FPBits::inf(Sign::NEG)); + const T zero = T(FPBits::zero(Sign::POS)); + const T neg_zero = T(FPBits::zero(Sign::NEG)); + + const T max_normal = T(FPBits::max_normal()); + const T min_normal = T(FPBits::min_normal()); + const T max_subnormal = T(FPBits::max_subnormal()); + const T min_subnormal = T(FPBits::min_subnormal()); public: void test_special_numbers(Func func) { diff --git a/libc/test/src/math/smoke/ILogbTest.h b/libc/test/src/math/smoke/ILogbTest.h index 0a50abc04f727..223de789999af 100644 --- a/libc/test/src/math/smoke/ILogbTest.h +++ b/libc/test/src/math/smoke/ILogbTest.h @@ -28,7 +28,7 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { using Sign = LIBC_NAMESPACE::fputil::Sign; EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::POS)))); EXPECT_EQ(FP_ILOGB0, func(T(FPBits::zero(Sign::NEG)))); - EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(1)))); + EXPECT_EQ(FP_ILOGBNAN, func(T(FPBits::build_quiet_nan(Sign::POS, 1)))); EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::POS)))); EXPECT_EQ(INT_MAX, func(T(FPBits::inf(Sign::NEG)))); } @@ -76,11 +76,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { void test_subnormal_range(typename ILogbFunc::Func func) { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using StorageType = typename FPBits::StorageType; + constexpr StorageType MIN_SUBNORMAL = FPBits::min_subnormal().uintval(); + constexpr StorageType MAX_SUBNORMAL = FPBits::max_subnormal().uintval(); constexpr StorageType COUNT = 10'001; - constexpr StorageType STEP = - (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; - for (StorageType v = FPBits::MIN_SUBNORMAL; v <= FPBits::MAX_SUBNORMAL; - v += STEP) { + constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; + for (StorageType v = MIN_SUBNORMAL; v <= MAX_SUBNORMAL; v += STEP) { T x = T(FPBits(v)); if (isnan(x) || isinf(x) || x == 0.0) continue; @@ -95,11 +95,11 @@ class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { void test_normal_range(typename ILogbFunc::Func func) { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using StorageType = typename FPBits::StorageType; + constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); + constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); constexpr StorageType COUNT = 10'001; - constexpr StorageType STEP = - (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT; - for (StorageType v = FPBits::MIN_NORMAL; v <= FPBits::MAX_NORMAL; - v += STEP) { + constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT; + for (StorageType v = MIN_NORMAL; v <= MAX_NORMAL; v += STEP) { T x = T(FPBits(v)); if (isnan(x) || isinf(x) || x == 0.0) continue; diff --git a/libc/test/src/math/smoke/LdExpTest.h b/libc/test/src/math/smoke/LdExpTest.h index 25120ba3646fd..3a4baabbf10e6 100644 --- a/libc/test/src/math/smoke/LdExpTest.h +++ b/libc/test/src/math/smoke/LdExpTest.h @@ -29,7 +29,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); // A normalized mantissa to be used with tests. static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x1234; diff --git a/libc/test/src/math/smoke/NextAfterTest.h b/libc/test/src/math/smoke/NextAfterTest.h index bdf3da627180a..1dd07b3d2f93d 100644 --- a/libc/test/src/math/smoke/NextAfterTest.h +++ b/libc/test/src/math/smoke/NextAfterTest.h @@ -38,12 +38,14 @@ class NextAfterTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); - - const StorageType min_subnormal = FPBits::MIN_SUBNORMAL; - const StorageType max_subnormal = FPBits::MAX_SUBNORMAL; - const StorageType min_normal = FPBits::MIN_NORMAL; - const StorageType max_normal = FPBits::MAX_NORMAL; + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); + + static constexpr StorageType min_subnormal = + FPBits::min_subnormal().uintval(); + static constexpr StorageType max_subnormal = + FPBits::max_subnormal().uintval(); + static constexpr StorageType min_normal = FPBits::min_normal().uintval(); + static constexpr StorageType max_normal = FPBits::max_normal().uintval(); public: typedef T (*NextAfterFunc)(T, T); diff --git a/libc/test/src/math/smoke/NextTowardTest.h b/libc/test/src/math/smoke/NextTowardTest.h index af4e0ab14531c..d65cc5d84d35a 100644 --- a/libc/test/src/math/smoke/NextTowardTest.h +++ b/libc/test/src/math/smoke/NextTowardTest.h @@ -40,16 +40,18 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); - - const long double to_zero = ToFPBits::zero(); - const long double to_neg_zero = ToFPBits::zero(Sign::NEG); - const long double to_nan = ToFPBits::build_quiet_nan(1); - - const StorageType min_subnormal = FPBits::MIN_SUBNORMAL; - const StorageType max_subnormal = FPBits::MAX_SUBNORMAL; - const StorageType min_normal = FPBits::MIN_NORMAL; - const StorageType max_normal = FPBits::MAX_NORMAL; + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); + + const long double to_zero = ToFPBits::zero().get_val(); + const long double to_neg_zero = ToFPBits::zero(Sign::NEG).get_val(); + const long double to_nan = ToFPBits::build_quiet_nan(Sign::POS, 1).get_val(); + + static constexpr StorageType min_subnormal = + FPBits::min_subnormal().uintval(); + static constexpr StorageType max_subnormal = + FPBits::max_subnormal().uintval(); + static constexpr StorageType min_normal = FPBits::min_normal().uintval(); + static constexpr StorageType max_normal = FPBits::max_normal().uintval(); public: typedef T (*NextTowardFunc)(T, long double); diff --git a/libc/test/src/math/smoke/RIntTest.h b/libc/test/src/math/smoke/RIntTest.h index b242c7e441b69..7bbbe54301570 100644 --- a/libc/test/src/math/smoke/RIntTest.h +++ b/libc/test/src/math/smoke/RIntTest.h @@ -35,7 +35,7 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); public: void testSpecialNumbers(RIntFunc func) { diff --git a/libc/test/src/math/smoke/RemQuoTest.h b/libc/test/src/math/smoke/RemQuoTest.h index 93e20747e5263..5f5cbd4964a62 100644 --- a/libc/test/src/math/smoke/RemQuoTest.h +++ b/libc/test/src/math/smoke/RemQuoTest.h @@ -25,7 +25,7 @@ class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test { const T neg_inf = T(FPBits::inf(Sign::NEG)); const T zero = T(FPBits::zero(Sign::POS)); const T neg_zero = T(FPBits::zero(Sign::NEG)); - const T nan = T(FPBits::build_quiet_nan(1)); + const T nan = T(FPBits::build_quiet_nan(Sign::POS, 1)); public: typedef T (*RemQuoFunc)(T, T, int *); diff --git a/libc/test/src/math/smoke/RoundToIntegerTest.h b/libc/test/src/math/smoke/RoundToIntegerTest.h index 2703b78f00e0f..77c65aa492e22 100644 --- a/libc/test/src/math/smoke/RoundToIntegerTest.h +++ b/libc/test/src/math/smoke/RoundToIntegerTest.h @@ -30,11 +30,17 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test { using StorageType = typename FPBits::StorageType; using Sign = LIBC_NAMESPACE::fputil::Sign; - const F zero = F(LIBC_NAMESPACE::fputil::FPBits::zero(Sign::POS)); - const F neg_zero = F(LIBC_NAMESPACE::fputil::FPBits::zero(Sign::NEG)); - const F inf = F(LIBC_NAMESPACE::fputil::FPBits::inf(Sign::POS)); - const F neg_inf = F(LIBC_NAMESPACE::fputil::FPBits::inf(Sign::NEG)); - const F nan = F(LIBC_NAMESPACE::fputil::FPBits::build_quiet_nan(1)); + const F zero = F(FPBits::zero(Sign::POS)); + const F neg_zero = F(FPBits::zero(Sign::NEG)); + const F inf = F(FPBits::inf(Sign::POS)); + const F neg_inf = F(FPBits::inf(Sign::NEG)); + const F nan = F(FPBits::build_quiet_nan(Sign::POS, 1)); + + static constexpr StorageType MAX_SUBNORMAL = + FPBits::max_subnormal().uintval(); + static constexpr StorageType MIN_SUBNORMAL = + FPBits::min_subnormal().uintval(); + static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1); static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1); @@ -111,10 +117,8 @@ class RoundToIntegerTestTemplate : public LIBC_NAMESPACE::testing::Test { void testSubnormalRange(RoundToIntegerFunc func) { constexpr StorageType COUNT = 1'000'001; - constexpr StorageType STEP = - (FPBits::MAX_SUBNORMAL - FPBits::MIN_SUBNORMAL) / COUNT; - for (StorageType i = FPBits::MIN_SUBNORMAL; i <= FPBits::MAX_SUBNORMAL; - i += STEP) { + constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT; + for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) { F x = F(FPBits(i)); if (x == F(0.0)) continue; diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp index 344853beaf9fa..b22378b22ab12 100644 --- a/libc/test/src/stdio/sprintf_test.cpp +++ b/libc/test/src/stdio/sprintf_test.cpp @@ -585,8 +585,10 @@ TEST(LlvmLibcSPrintfTest, OctConv) { TEST_F(LlvmLibcSPrintfTest, FloatHexExpConv) { ForceRoundingMode r(RoundingMode::Nearest); - double inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan(1); + double inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); written = LIBC_NAMESPACE::sprintf(buff, "%a", 1.0); ASSERT_STREQ_LEN(written, buff, "0x1p+0"); @@ -949,11 +951,15 @@ TEST_F(LlvmLibcSPrintfTest, FloatHexExpConv) { TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) { ForceRoundingMode r(RoundingMode::Nearest); - double inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan(1); - long double ld_inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - long double ld_nan = - LIBC_NAMESPACE::fputil::FPBits::build_nan(1); + double inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); + long double ld_inf = + LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + long double ld_nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); char big_buff[10000]; // Used for long doubles and other extremely wide // numbers. @@ -1790,8 +1796,10 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) { TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) { ForceRoundingMode r(RoundingMode::Nearest); - double inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan(1); + double inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); written = LIBC_NAMESPACE::sprintf(buff, "%e", 1.0); ASSERT_STREQ_LEN(written, buff, "1.000000e+00"); @@ -2422,8 +2430,10 @@ TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) { TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) { ForceRoundingMode r(RoundingMode::Nearest); - double inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan(1); + double inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.0); ASSERT_STREQ_LEN(written, buff, "1"); diff --git a/libc/test/src/stdio/sscanf_test.cpp b/libc/test/src/stdio/sscanf_test.cpp index db3c48cdbf7a2..db67c25029133 100644 --- a/libc/test/src/stdio/sscanf_test.cpp +++ b/libc/test/src/stdio/sscanf_test.cpp @@ -230,8 +230,10 @@ TEST(LlvmLibcSScanfTest, FloatConvSimple) { int ret_val; float result = 0; - float inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - float nan = LIBC_NAMESPACE::fputil::FPBits::build_nan(1); + float inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + float nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); ret_val = LIBC_NAMESPACE::sscanf("123", "%f", &result); EXPECT_EQ(ret_val, 1); @@ -294,9 +296,10 @@ TEST(LlvmLibcSScanfTest, FloatConvLengthModifier) { double d_result = 0; long double ld_result = 0; - double d_inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - long double ld_nan = - LIBC_NAMESPACE::fputil::FPBits::build_nan(1); + double d_inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + long double ld_nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); ret_val = LIBC_NAMESPACE::sscanf("123", "%lf", &d_result); EXPECT_EQ(ret_val, 1); @@ -391,8 +394,10 @@ TEST(LlvmLibcSScanfTest, FloatConvComplexParsing) { int ret_val; float result = 0; - float inf = LIBC_NAMESPACE::fputil::FPBits::inf(); - float nan = LIBC_NAMESPACE::fputil::FPBits::build_nan(1); + float inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + float nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); ret_val = LIBC_NAMESPACE::sscanf("0x1.0e3", "%f", &result); EXPECT_EQ(ret_val, 1); @@ -463,7 +468,7 @@ TEST(LlvmLibcSScanfTest, FloatConvMaxWidth) { int ret_val; float result = 0; - float inf = LIBC_NAMESPACE::fputil::FPBits::inf(); + float inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); ret_val = LIBC_NAMESPACE::sscanf("123", "%3f", &result); EXPECT_EQ(ret_val, 1); diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp index b6ca525db6cf7..06a231c7d94d0 100644 --- a/libc/utils/MPFRWrapper/MPFRUtils.cpp +++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp @@ -49,7 +49,7 @@ template <> struct ExtraPrecision { template static inline unsigned int get_precision(double ulp_tolerance) { if (ulp_tolerance <= 0.5) { - return LIBC_NAMESPACE::fputil::FPBits::MANTISSA_PRECISION; + return LIBC_NAMESPACE::fputil::FPBits::FRACTION_LEN + 1; } else { return ExtraPrecision::VALUE; }