diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 63eeba85f15e5..93e32ba7cc941 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -162,9 +162,9 @@ struct FPRepBase : public internal::FPLayout { ? bit_at(SIG_LEN - 1) | bit_at(SIG_LEN - 2) // 0b1100... : bit_at(SIG_LEN - 1); // 0b1000... - // If a number x is a NAN, then it is a signalling NAN if: - // SIGNALING_NAN_MASK & bits(x) != 0 - LIBC_INLINE_VAR static constexpr StorageType SIGNALING_NAN_MASK = + // Mask to generate a default signaling NAN. Any NAN that is not + // a quiet NAN is considered a signaling NAN. + LIBC_INLINE_VAR static constexpr StorageType DEFAULT_SIGNALING_NAN = fp_type == FPType::X86_Binary80 ? bit_at(SIG_LEN - 1) | bit_at(SIG_LEN - 3) // 0b1010... : bit_at(SIG_LEN - 2); // 0b0100... @@ -356,7 +356,7 @@ template struct FPBits : public internal::FPRep()> { } LIBC_INLINE constexpr bool is_quiet_nan() const { - return (bits & EXP_SIG_MASK) == (EXP_MASK | QUIET_NAN_MASK); + return (bits & EXP_SIG_MASK) >= (EXP_MASK | QUIET_NAN_MASK); } LIBC_INLINE constexpr bool is_inf_or_nan() const { diff --git a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h index 8abc0c87af0d2..c18abcee77ea5 100644 --- a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h +++ b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h @@ -114,6 +114,10 @@ struct FPBits : public internal::FPRep { (get_biased_exponent() != 0 && get_implicit_bit() == 0); } + LIBC_INLINE constexpr bool is_quiet_nan() const { + return (bits & EXP_SIG_MASK) >= (EXP_MASK | QUIET_NAN_MASK); + } + // Methods below this are used by tests. LIBC_INLINE static constexpr long double zero(bool sign = false) { diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp index fa743855c4861..e2dbe248ef213 100644 --- a/libc/test/src/__support/FPUtil/fpbits_test.cpp +++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp @@ -69,6 +69,9 @@ TEST(LlvmLibcFPBitsTest, FloatType) { EXPECT_EQ(negnum.uintval(), static_cast(0xBF900000)); EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), "0xBF900000 = (S: 1, E: 0x007F, M: 0x00100000)"); + + FloatBits quiet_nan = FloatBits(FloatBits::build_quiet_nan(1)); + EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } TEST(LlvmLibcFPBitsTest, DoubleType) { @@ -129,6 +132,9 @@ TEST(LlvmLibcFPBitsTest, DoubleType) { EXPECT_EQ(negnum.uintval(), static_cast(0xBFF2000000000000)); EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), "0xBFF2000000000000 = (S: 1, E: 0x03FF, M: 0x0002000000000000)"); + + DoubleBits quiet_nan = DoubleBits(DoubleBits::build_quiet_nan(1)); + EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } #ifdef LIBC_TARGET_ARCH_IS_X86 @@ -210,6 +216,9 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) { LIBC_NAMESPACE::str(negnum).c_str(), "0x000000000000BFFF9000000000000000 = " "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)"); + + LongDoubleBits quiet_nan = LongDoubleBits(LongDoubleBits::build_quiet_nan(1)); + EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } #else TEST(LlvmLibcFPBitsTest, LongDoubleType) { @@ -284,6 +293,9 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) { EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), "0xBFFF2000000000000000000000000000 = " "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)"); + + LongDoubleBits quiet_nan = LongDoubleBits(LongDoubleBits::build_quiet_nan(1)); + EXPECT_EQ(quiet_nan.is_quiet_nan(), true); #endif } #endif @@ -357,5 +369,8 @@ TEST(LlvmLibcFPBitsTest, Float128Type) { EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), "0xBFFF2000000000000000000000000000 = " "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)"); + + Float128Bits quiet_nan = Float128Bits(Float128Bits::build_quiet_nan(1)); + EXPECT_EQ(quiet_nan.is_quiet_nan(), true); } #endif // LIBC_COMPILER_HAS_FLOAT128