diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 6da89091a8ced..90b6e406e0f31 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -127,7 +127,11 @@ template <> struct FPLayout { }; template <> struct FPLayout { +#if __SIZEOF_LONG_DOUBLE__ == 12 + using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>; +#else using StorageType = UInt128; +#endif LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; LIBC_INLINE_VAR static constexpr int EXP_LEN = 15; LIBC_INLINE_VAR static constexpr int SIG_LEN = 64; 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 053348d4c975d..9492d52da0455 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 @@ -21,7 +21,8 @@ namespace LIBC_NAMESPACE_DECL { namespace fputil { namespace x86 { -LIBC_INLINE void normalize(int &exponent, UInt128 &mantissa) { +LIBC_INLINE void normalize(int &exponent, + FPBits::StorageType &mantissa) { const unsigned int shift = static_cast( cpp::countl_zero(static_cast(mantissa)) - (8 * sizeof(uint64_t) - 1 - FPBits::FRACTION_LEN)); diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h index bea0abc84b213..a95ab4ff8e1ab 100644 --- a/libc/src/__support/big_int.h +++ b/libc/src/__support/big_int.h @@ -469,7 +469,7 @@ struct BigInt { !cpp::is_same_v>> LIBC_INLINE constexpr BigInt(T v) { constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT; - const bool is_neg = Signed && (v < 0); + const bool is_neg = v < 0; for (size_t i = 0; i < WORD_COUNT; ++i) { if (v == 0) { extend(i, is_neg); @@ -504,6 +504,12 @@ struct BigInt { // TODO: Reuse the Sign type. LIBC_INLINE constexpr bool is_neg() const { return SIGNED && get_msb(); } + template + LIBC_INLINE constexpr explicit + operator BigInt() const { + return BigInt(this); + } + template LIBC_INLINE constexpr explicit operator T() const { return to(); } @@ -1058,6 +1064,8 @@ struct WordTypeSelector : cpp::type_identity< // Except if we request 16 or 32 bits explicitly. template <> struct WordTypeSelector<16> : cpp::type_identity {}; template <> struct WordTypeSelector<32> : cpp::type_identity {}; +template <> struct WordTypeSelector<96> : cpp::type_identity {}; + template using WordTypeSelectorT = typename WordTypeSelector::type; } // namespace internal diff --git a/libc/src/__support/float_to_string.h b/libc/src/__support/float_to_string.h index e2e06cd0492a9..d5de6f38cb655 100644 --- a/libc/src/__support/float_to_string.h +++ b/libc/src/__support/float_to_string.h @@ -373,23 +373,12 @@ LIBC_INLINE UInt get_table_negative_df(int exponent, size_t i) { return result; } -LIBC_INLINE uint32_t fast_uint_mod_1e9(const UInt &val) { - // The formula for mult_const is: - // 1 + floor((2^(bits in target integer size + log_2(divider))) / divider) - // Where divider is 10^9 and target integer size is 128. - const UInt mult_const( - {0x31680A88F8953031u, 0x89705F4136B4A597u, 0}); - const auto middle = (mult_const * val); - const uint64_t result = static_cast(middle[2]); - const uint64_t shifted = result >> 29; - return static_cast(static_cast(val) - - (EXP10_9 * shifted)); -} - LIBC_INLINE uint32_t mul_shift_mod_1e9(const FPBits::StorageType mantissa, const UInt &large, const int32_t shift_amount) { - UInt val(large); + // make sure the number of bits is always divisible by 64 + UInt val( + large); val = (val * mantissa) >> shift_amount; return static_cast( val.div_uint_half_times_pow_2(static_cast(EXP10_9), 0).value()); diff --git a/libc/src/__support/integer_literals.h b/libc/src/__support/integer_literals.h index af3da1c443d7b..4c5c4c4166681 100644 --- a/libc/src/__support/integer_literals.h +++ b/libc/src/__support/integer_literals.h @@ -165,6 +165,10 @@ LIBC_INLINE constexpr T parse_with_prefix(const char *ptr) { } // namespace internal +LIBC_INLINE constexpr UInt<96> operator""_u96(const char *x) { + return internal::parse_with_prefix>(x); +} + LIBC_INLINE constexpr UInt128 operator""_u128(const char *x) { return internal::parse_with_prefix(x); } diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index a1f4eef03fc3c..80ea334d15c03 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -206,7 +206,7 @@ eisel_lemire(ExpandedFloat init_num, using FPBits = typename fputil::FPBits; using StorageType = typename FPBits::StorageType; - StorageType mantissa = init_num.mantissa; + UInt128 mantissa = init_num.mantissa; int32_t exp10 = init_num.exponent; // Exp10 Range @@ -225,7 +225,8 @@ eisel_lemire(ExpandedFloat init_num, } // Normalization - uint32_t clz = cpp::countl_zero(mantissa); + uint32_t clz = cpp::countl_zero(mantissa) - + ((sizeof(UInt128) - sizeof(StorageType)) * CHAR_BIT); mantissa <<= clz; int32_t exp2 = @@ -276,9 +277,8 @@ eisel_lemire(ExpandedFloat init_num, // Shifting to 65 bits for 80 bit floats and 113 bits for 128 bit floats uint32_t msb = static_cast(final_approx_upper >> (FPBits::STORAGE_LEN - 1)); - StorageType final_mantissa = - final_approx_upper >> - (msb + FPBits::STORAGE_LEN - (FPBits::FRACTION_LEN + 3)); + UInt128 final_mantissa = final_approx_upper >> (msb + FPBits::STORAGE_LEN - + (FPBits::FRACTION_LEN + 3)); exp2 -= static_cast(1 ^ msb); // same as !msb if (round == RoundDirection::Nearest) { @@ -315,7 +315,7 @@ eisel_lemire(ExpandedFloat init_num, } ExpandedFloat output; - output.mantissa = final_mantissa; + output.mantissa = static_cast(final_mantissa); output.exponent = exp2; return output; } @@ -558,7 +558,7 @@ clinger_fast_path(ExpandedFloat init_num, FPBits result; T float_mantissa; - if constexpr (cpp::is_same_v>) { + if constexpr (is_big_int_v || sizeof(T) > sizeof(uint64_t)) { float_mantissa = (static_cast(uint64_t(mantissa >> 64)) * static_cast(0x1.0p64)) + static_cast(uint64_t(mantissa)); diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp index ad5722f99a436..afb1368f00905 100644 --- a/libc/test/UnitTest/LibcTest.cpp +++ b/libc/test/UnitTest/LibcTest.cpp @@ -44,7 +44,6 @@ cpp::enable_if_t<(cpp::is_integral_v && (sizeof(T) > sizeof(uint64_t))) || is_big_int_v, cpp::string> describeValue(T Value) { - static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); const IntegerToString buffer(Value); return buffer.view(); } @@ -242,6 +241,7 @@ TEST_SPECIALIZATION(__uint128_t); TEST_SPECIALIZATION(LIBC_NAMESPACE::Int<128>); +TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<96>); TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<128>); TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<192>); TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<256>); diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp index bcab0286480c3..edb04c24ae387 100644 --- a/libc/test/src/__support/FPUtil/fpbits_test.cpp +++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp @@ -8,12 +8,14 @@ #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/fpbits_str.h" +#include "src/__support/big_int.h" #include "src/__support/integer_literals.h" #include "src/__support/macros/properties/types.h" #include "src/__support/sign.h" // Sign #include "test/UnitTest/Test.h" using LIBC_NAMESPACE::Sign; +using LIBC_NAMESPACE::UInt; using LIBC_NAMESPACE::fputil::FPBits; using LIBC_NAMESPACE::fputil::FPType; using LIBC_NAMESPACE::fputil::internal::FPRep; @@ -21,6 +23,7 @@ using LIBC_NAMESPACE::fputil::internal::FPRep; using LIBC_NAMESPACE::operator""_u16; using LIBC_NAMESPACE::operator""_u32; using LIBC_NAMESPACE::operator""_u64; +using LIBC_NAMESPACE::operator""_u96; using LIBC_NAMESPACE::operator""_u128; TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary16) { @@ -124,6 +127,7 @@ TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary128) { TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80) { using Rep = FPRep; +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ( 0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000000_u128, UInt128(Rep::zero())); @@ -151,11 +155,43 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80) { EXPECT_EQ( 0b0'1111111111111111100000000000000000000000000000000000000000000000000000000000000_u128, UInt128(Rep::quiet_nan())); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ( + 0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::zero())); + EXPECT_EQ( + 0b0'0111111111111111000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::one())); + EXPECT_EQ( + 0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000001_u96, + UInt<96>(Rep::min_subnormal())); + EXPECT_EQ( + 0b0'0000000000000000111111111111111111111111111111111111111111111111111111111111111_u96, + UInt<96>(Rep::max_subnormal())); + EXPECT_EQ( + 0b0'0000000000000011000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::min_normal())); + EXPECT_EQ( + 0b0'1111111111111101111111111111111111111111111111111111111111111111111111111111111_u96, + UInt<96>(Rep::max_normal())); + EXPECT_EQ( + 0b0'1111111111111111000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::inf())); + EXPECT_EQ( + 0b0'1111111111111111010000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::signaling_nan())); + EXPECT_EQ( + 0b0'1111111111111111100000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::quiet_nan())); +#else +#error "unhandled long double type" +#endif } TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) { using Rep = FPRep; +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_TRUE( // NAN : Pseudo-Infinity Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000_u128) .is_nan()); @@ -192,6 +228,46 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) { EXPECT_FALSE( // Normalized Rep(0b0'111111111111110'1000000000000000000000000000000000000000000000000000000000000000_u128) .is_nan()); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_TRUE( // NAN : Pseudo-Infinity + Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Pseudo Not a Number + Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Pseudo Not a Number + Rep(0b0'111111111111111'0100000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Signalling Not a Number + Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Floating-point Indefinite + Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Quiet Not a Number + Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Unnormal + Rep(0b0'111111111111110'0000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_FALSE( // Zero + Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_FALSE( // Subnormal + Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_FALSE( // Pseudo Denormal + Rep(0b0'000000000000000'1000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_FALSE( // Infinity + Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_FALSE( // Normalized + Rep(0b0'111111111111110'1000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); +#else +#error "unhandled long double type" +#endif } enum class FP { @@ -430,6 +506,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) { #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 TEST(LlvmLibcFPBitsTest, X86LongDoubleType) { using LongDoubleBits = FPBits; + using Rep = FPRep; EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(), "(+Infinity)"); @@ -441,62 +518,117 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) { LongDoubleBits zero(0.0l); EXPECT_TRUE(zero.is_pos()); EXPECT_EQ(zero.get_biased_exponent(), 0_u16); - EXPECT_EQ(zero.get_mantissa(), 0_u128); - EXPECT_EQ(zero.uintval(), 0_u128); + EXPECT_EQ(zero.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); + EXPECT_EQ(zero.uintval(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_STREQ( LIBC_NAMESPACE::str(zero).c_str(), "0x00000000000000000000000000000000 = " "(S: 0, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(), + "0x000000000000000000000000 = " + "(S: 0, E: 0x0000, I: 0, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits negzero(-0.0l); EXPECT_TRUE(negzero.is_neg()); EXPECT_EQ(negzero.get_biased_exponent(), 0_u16); - EXPECT_EQ(negzero.get_mantissa(), 0_u128); + EXPECT_EQ(negzero.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(negzero.uintval(), 0x8000'00000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(negzero).c_str(), "0x00000000000080000000000000000000 = " "(S: 1, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(negzero.uintval(), 0x8000'00000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(), + "0x000080000000000000000000 = " + "(S: 1, E: 0x0000, I: 0, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits one(1.0l); EXPECT_TRUE(one.is_pos()); EXPECT_EQ(one.get_biased_exponent(), 0x3FFF_u16); - EXPECT_EQ(one.get_mantissa(), 0_u128); + EXPECT_EQ(one.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(one.uintval(), 0x3FFF'80000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(one).c_str(), "0x0000000000003FFF8000000000000000 = " "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(one.uintval(), 0x3FFF'80000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(), + "0x00003FFF8000000000000000 = " + "(S: 0, E: 0x3FFF, I: 1, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits negone(-1.0l); EXPECT_TRUE(negone.is_neg()); EXPECT_EQ(negone.get_biased_exponent(), 0x3FFF_u16); - EXPECT_EQ(negone.get_mantissa(), 0_u128); + EXPECT_EQ(negone.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(negone.uintval(), 0xBFFF'80000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(negone).c_str(), "0x000000000000BFFF8000000000000000 = " "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(negone.uintval(), 0xBFFF'80000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(), + "0x0000BFFF8000000000000000 = " + "(S: 1, E: 0x3FFF, I: 1, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits num(1.125l); EXPECT_TRUE(num.is_pos()); EXPECT_EQ(num.get_biased_exponent(), 0x3FFF_u16); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(num.get_mantissa(), 0x10000000'00000000_u128); EXPECT_EQ(num.uintval(), 0x3FFF'90000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(num).c_str(), "0x0000000000003FFF9000000000000000 = " "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(num.get_mantissa(), 0x10000000'00000000_u96); + EXPECT_EQ(num.uintval(), 0x3FFF'90000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(), + "0x00003FFF9000000000000000 = " + "(S: 0, E: 0x3FFF, I: 1, M: 0x000000001000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits negnum(-1.125l); EXPECT_TRUE(negnum.is_neg()); EXPECT_EQ(negnum.get_biased_exponent(), 0x3FFF_u16); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(negnum.get_mantissa(), 0x10000000'00000000_u128); EXPECT_EQ(negnum.uintval(), 0xBFFF'90000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(negnum).c_str(), "0x000000000000BFFF9000000000000000 = " "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(negnum.get_mantissa(), 0x10000000'00000000_u96); + EXPECT_EQ(negnum.uintval(), 0xBFFF'90000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), + "0x0000BFFF9000000000000000 = " + "(S: 1, E: 0x3FFF, I: 1, M: 0x000000001000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits quiet_nan = LongDoubleBits::quiet_nan(); EXPECT_EQ(quiet_nan.is_quiet_nan(), true); diff --git a/libc/test/src/__support/big_int_test.cpp b/libc/test/src/__support/big_int_test.cpp index 471ca72a8f6e0..2666ed978dad7 100644 --- a/libc/test/src/__support/big_int_test.cpp +++ b/libc/test/src/__support/big_int_test.cpp @@ -1067,4 +1067,12 @@ TEST(LlvmLibcUIntClassTest, SignedOtherWordTypeCastTests) { ASSERT_TRUE(bigger_back_plus_a + bigger_back_minus_a == zero_96); } +TEST(LlvmLibcUIntClassTest, MixedSignednessOtherWordTypeCastTests) { + using LL_UInt96 = BigInt<96, false, uint32_t>; + LL_UInt96 x = -123; + // ensure that -123 gets extended, even though the input type is signed while + // the BigInt is unsigned. + ASSERT_EQ(int64_t(x), int64_t(-123)); +} + } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/__support/str_to_long_double_test.cpp b/libc/test/src/__support/str_to_long_double_test.cpp index 9efa457aac957..fa7d600f9bff4 100644 --- a/libc/test/src/__support/str_to_long_double_test.cpp +++ b/libc/test/src/__support/str_to_long_double_test.cpp @@ -30,12 +30,23 @@ TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80Simple) { } TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80LongerMantissa) { +#if __SIZEOF_LONG_DOUBLE__ == 16 eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 0, 0x91a2b3c091a2b3c1, 16507); eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 300, 0xd97757de56adb65c, 17503); eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, -300, 0xc30feb9a7618457d, 15510); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + eisel_lemire_test(0x12345678'12345678'12345678_u96, 0, 0x91a2b3c091a2b3c1, + 16475); + eisel_lemire_test(0x12345678'12345678'12345678_u96, 300, 0xd97757de56adb65c, + 17471); + eisel_lemire_test(0x12345678'12345678'12345678_u96, -300, 0xc30feb9a7618457d, + 15478); +#else +#error "unhandled long double type" +#endif } // These tests check numbers at the edge of the DETAILED_POWERS_OF_TEN table. diff --git a/libc/test/src/math/smoke/CanonicalizeTest.h b/libc/test/src/math/smoke/CanonicalizeTest.h index 3baf60c3140ff..f22a282b1843b 100644 --- a/libc/test/src/math/smoke/CanonicalizeTest.h +++ b/libc/test/src/math/smoke/CanonicalizeTest.h @@ -18,6 +18,10 @@ #include "hdr/math_macros.h" +#if __SIZEOF_LONG_DOUBLE__ != 16 && __SIZEOF_LONG_DOUBLE__ != 12 +#error "unhandled long double type" +#endif + #define TEST_SPECIAL(x, y, expected, expected_exception) \ EXPECT_EQ(expected, f(&x, &y)); \ EXPECT_FP_EXCEPTION(expected_exception); \ @@ -25,6 +29,7 @@ #define TEST_REGULAR(x, y, expected) TEST_SPECIAL(x, y, expected, 0) +using LIBC_NAMESPACE::operator""_u96; using LIBC_NAMESPACE::operator""_u128; template @@ -61,7 +66,11 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { // Exponent | Significand | Meaning // | Bits 63-62 | Bits 61-0 | // All Ones | 00 | Zero | Pseudo Infinity, Value = SNaN +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test1(0x00000000'00007FFF'00000000'00000000_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test1(0x00007FFF'00000000'00000000_u96); +#endif const T test1_val = test1.get_val(); TEST_SPECIAL(cx, test1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); @@ -69,22 +78,38 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { // Exponent | Significand | Meaning // | Bits 63-62 | Bits 61-0 | // All Ones | 00 | Non-Zero | Pseudo NaN, Value = SNaN +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test2_1(0x00000000'00007FFF'00000000'00000001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_1(0x00007FFF'00000000'00000001_u96); +#endif const T test2_1_val = test2_1.get_val(); TEST_SPECIAL(cx, test2_1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test2_2(0x00000000'00007FFF'00000042'70000001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_2(0x00007FFF'00000042'70000001_u96); +#endif const T test2_2_val = test2_2.get_val(); TEST_SPECIAL(cx, test2_2_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test2_3(0x00000000'00007FFF'00000000'08261001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_3(0x00007FFF'00000000'08261001_u96); +#endif const T test2_3_val = test2_3.get_val(); TEST_SPECIAL(cx, test2_3_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test2_4(0x00000000'00007FFF'00007800'08261001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_4(0x00007FFF'00007800'08261001_u96); +#endif const T test2_4_val = test2_4.get_val(); TEST_SPECIAL(cx, test2_4_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); @@ -92,22 +117,38 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { // Exponent | Significand | Meaning // | Bits 63-62 | Bits 61-0 | // All Ones | 01 | Anything | Pseudo NaN, Value = SNaN +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test3_1(0x00000000'00007FFF'40000000'00000000_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_1(0x00007FFF'40000000'00000000_u96); +#endif const T test3_1_val = test3_1.get_val(); TEST_SPECIAL(cx, test3_1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test3_2(0x00000000'00007FFF'40000042'70000001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_2(0x00007FFF'40000042'70000001_u96); +#endif const T test3_2_val = test3_2.get_val(); TEST_SPECIAL(cx, test3_2_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test3_3(0x00000000'00007FFF'40000000'08261001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_3(0x00007FFF'40000000'08261001_u96); +#endif const T test3_3_val = test3_3.get_val(); TEST_SPECIAL(cx, test3_3_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test3_4(0x00000000'00007FFF'40007800'08261001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_4(0x00007FFF'40007800'08261001_u96); +#endif const T test3_4_val = test3_4.get_val(); TEST_SPECIAL(cx, test3_4_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); @@ -116,19 +157,31 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { // | Bit 63 | Bits 62-0 | // All zeroes | One | Anything | Pseudo Denormal, Value = // | | | (−1)**s × m × 2**−16382 +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test4_1(0x00000000'00000000'80000000'00000000_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test4_1(0x00000000'80000000'00000000_u96); +#endif const T test4_1_val = test4_1.get_val(); TEST_SPECIAL(cx, test4_1_val, 0, 0); EXPECT_FP_EQ( cx, FPBits::make_value(test4_1.get_explicit_mantissa(), 0).get_val()); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test4_2(0x00000000'00000000'80000042'70000001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test4_2(0x00000000'80000042'70000001_u96); +#endif const T test4_2_val = test4_2.get_val(); TEST_SPECIAL(cx, test4_2_val, 0, 0); EXPECT_FP_EQ( cx, FPBits::make_value(test4_2.get_explicit_mantissa(), 0).get_val()); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test4_3(0x00000000'00000000'80000000'08261001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test4_3(0x00000000'80000000'08261001_u96); +#endif const T test4_3_val = test4_3.get_val(); TEST_SPECIAL(cx, test4_3_val, 0, 0); EXPECT_FP_EQ( @@ -138,32 +191,56 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { // | Bit 63 | Bits 62-0 | // All Other | Zero | Anything | Unnormal, Value = SNaN // Values | | | +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test5_1(0x00000000'00000040'00000000'00000001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_1(0x00000040'00000000'00000001_u96); +#endif const T test5_1_val = test5_1.get_val(); TEST_SPECIAL(cx, test5_1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test5_2(0x00000000'00000230'00000042'70000001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_2(0x00000230'00000042'70000001_u96); +#endif const T test5_2_val = test5_2.get_val(); TEST_SPECIAL(cx, test5_2_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test5_3(0x00000000'00000560'00000000'08261001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_3(0x00000560'00000000'08261001_u96); +#endif const T test5_3_val = test5_3.get_val(); TEST_SPECIAL(cx, test5_3_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test5_4(0x00000000'00000780'00000028'16000000_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_4(0x00000780'00000028'16000000_u96); +#endif const T test5_4_val = test5_4.get_val(); TEST_SPECIAL(cx, test5_4_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test5_5(0x00000000'00000900'00000042'70000001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_5(0x00000900'00000042'70000001_u96); +#endif const T test5_5_val = test5_5.get_val(); TEST_SPECIAL(cx, test5_5_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 16 FPBits test5_6(0x00000000'00000AB0'00000000'08261001_u128); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_6(0x00000AB0'00000000'08261001_u96); +#endif const T test5_6_val = test5_6.get_val(); TEST_SPECIAL(cx, test5_6_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); diff --git a/libc/test/src/stdlib/strtold_test.cpp b/libc/test/src/stdlib/strtold_test.cpp index 2c9f542930bf8..b209c85b88e36 100644 --- a/libc/test/src/stdlib/strtold_test.cpp +++ b/libc/test/src/stdlib/strtold_test.cpp @@ -75,8 +75,9 @@ class LlvmLibcStrToLDTest : public LIBC_NAMESPACE::testing::Test { // +-- 15 Exponent Bits char *str_end = nullptr; - LIBC_NAMESPACE::fputil::FPBits expected_fp = - LIBC_NAMESPACE::fputil::FPBits(expectedRawData); + using FPBits = LIBC_NAMESPACE::fputil::FPBits; + FPBits expected_fp = + FPBits(static_cast(expectedRawData)); const int expected_errno = expectedErrno; LIBC_NAMESPACE::libc_errno = 0;