diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index a30e41f2d046..f972b97de1b0 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -135,6 +135,11 @@ template struct FPBits { return (bits & FloatProp::EXP_MANT_MASK) > FloatProp::EXPONENT_MASK; } + bool is_quiet_nan() const { + return (bits & FloatProp::EXP_MANT_MASK) == + (FloatProp::EXPONENT_MASK | FloatProp::QUIET_NAN_MASK); + } + bool is_inf_or_nan() const { return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK; } diff --git a/libc/src/__support/FPUtil/builtin_wrappers.h b/libc/src/__support/FPUtil/builtin_wrappers.h index 3924610bc716..fc524d24d623 100644 --- a/libc/src/__support/FPUtil/builtin_wrappers.h +++ b/libc/src/__support/FPUtil/builtin_wrappers.h @@ -65,22 +65,6 @@ template static inline int unsafe_clz(T val) { return __internal::clz(val); } -template static inline bool isnan(T val) { - return __builtin_isnan(val); -} - -template static inline bool isinf(T val) { - return __builtin_isinf(val); -} - -template static inline bool isfinite(T val) { - return __builtin_isfinite(val); -} - -inline float quiet_NaN(float) { return __builtin_nanf(""); } -inline double quiet_NaN(double) { return __builtin_nan(""); } -inline long double quiet_NaN(long double) { return __builtin_nanl(""); } - } // namespace fputil } // namespace __llvm_libc diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h index 3a03f931657a..d33acea8bafb 100644 --- a/libc/src/__support/FPUtil/generic/FMod.h +++ b/libc/src/__support/FPUtil/generic/FMod.h @@ -115,28 +115,36 @@ namespace generic { // https://man7.org/linux/man-pages/man3/fmod.3p.html // C standard for the function is not full, so not by default (although it can // be implemented in another handler. +// Signaling NaN converted to quiet NaN with FE_INVALID exception. +// https://www.open-std.org/JTC1/SC22/WG14/www/docs/n1011.htm template struct FModExceptionalInputHandler { static_assert(cpp::IsFloatingPointType::Value, "FModCStandardWrapper instantiated with invalid type."); static bool PreCheck(T x, T y, T &out) { - if (likely(y != 0 && fputil::isfinite(y) && fputil::isfinite(x))) { + using FPB = fputil::FPBits; + const T quiet_NaN = FPB::build_nan(FPB::FloatProp::QUIET_NAN_MASK); + FPB sx(x), sy(y); + if (likely(!sy.is_zero() && !sy.is_inf_or_nan() && !sx.is_inf_or_nan())) { return false; } - if (fputil::isnan(x) || fputil::isnan(y)) { - out = fputil::quiet_NaN(T(0)); + if (sx.is_nan() || sy.is_nan()) { + if ((sx.is_nan() && !sx.is_quiet_nan()) || + (sy.is_nan() && !sy.is_quiet_nan())) + fputil::set_except(FE_INVALID); + out = quiet_NaN; return true; } - if (fputil::isinf(x) || y == 0) { + if (sx.is_inf() || sy.is_zero()) { fputil::set_except(FE_INVALID); - out = with_errno(fputil::quiet_NaN(T(0)), EDOM); + out = with_errno(quiet_NaN, EDOM); return true; } - if (fputil::isinf(y)) { + if (sy.is_inf()) { out = x; return true; } diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h index 8761e8623de0..5f5d9bb00cde 100644 --- a/libc/src/__support/FPUtil/generic/sqrt.h +++ b/libc/src/__support/FPUtil/generic/sqrt.h @@ -51,8 +51,9 @@ inline void normalize(int &exponent, uint64_t &mantissa) { template <> inline void normalize(int &exponent, UInt128 &mantissa) { const uint64_t hi_bits = static_cast(mantissa >> 64); - const int shift = hi_bits ? (unsafe_clz(hi_bits) - 15) - : (unsafe_clz(static_cast(mantissa)) + 49); + const int shift = hi_bits + ? (unsafe_clz(hi_bits) - 15) + : (unsafe_clz(static_cast(mantissa)) + 49); exponent -= shift; mantissa <<= shift; }