From a78272f01c60635ee037176055788e88667f112d Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 27 Nov 2023 15:13:12 +0000 Subject: [PATCH 1/4] [libc] Fix forward octal prefix --- libc/src/__support/macros/properties/float.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/src/__support/macros/properties/float.h b/libc/src/__support/macros/properties/float.h index 3bfd041568936..b1d40ff7237f8 100644 --- a/libc/src/__support/macros/properties/float.h +++ b/libc/src/__support/macros/properties/float.h @@ -37,7 +37,7 @@ #endif #endif #if defined(LIBC_TARGET_ARCH_IS_AARCH64) -#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 0900)) || \ +#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 900)) || \ (defined(LIBC_COMPILER_GCC_VER) && (LIBC_COMPILER_GCC_VER >= 1301)) #define LIBC_COMPILER_HAS_C23_FLOAT16 #endif @@ -61,7 +61,7 @@ using float16 = _Float16; defined(LIBC_TARGET_ARCH_IS_X86_64)) #define LIBC_COMPILER_HAS_C23_FLOAT128 #endif -#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 0500)) && \ +#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 500)) && \ (defined(LIBC_TARGET_ARCH_IS_X86_64)) #define LIBC_COMPILER_HAS_FLOAT128_EXTENSION #endif From a09085a935a58028b54e6725d5e8f73dbc402c24 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 27 Nov 2023 15:18:27 +0000 Subject: [PATCH 2/4] fix format --- libc/src/__support/macros/properties/float.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/src/__support/macros/properties/float.h b/libc/src/__support/macros/properties/float.h index b1d40ff7237f8..7e00ddc8f0cd3 100644 --- a/libc/src/__support/macros/properties/float.h +++ b/libc/src/__support/macros/properties/float.h @@ -37,7 +37,7 @@ #endif #endif #if defined(LIBC_TARGET_ARCH_IS_AARCH64) -#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 900)) || \ +#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 900)) || \ (defined(LIBC_COMPILER_GCC_VER) && (LIBC_COMPILER_GCC_VER >= 1301)) #define LIBC_COMPILER_HAS_C23_FLOAT16 #endif @@ -61,7 +61,7 @@ using float16 = _Float16; defined(LIBC_TARGET_ARCH_IS_X86_64)) #define LIBC_COMPILER_HAS_C23_FLOAT128 #endif -#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 500)) && \ +#if (defined(LIBC_COMPILER_CLANG_VER) && (LIBC_COMPILER_CLANG_VER >= 500)) && \ (defined(LIBC_TARGET_ARCH_IS_X86_64)) #define LIBC_COMPILER_HAS_FLOAT128_EXTENSION #endif From a9066ded4b11f8bc5c440a8b593f30d414998540 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 27 Nov 2023 13:58:18 +0000 Subject: [PATCH 3/4] [libc][NFC] Decouple FP properties from C++ types We simplify the floating point properties by splitting concerns: - We define all distinct floating point formats in the `FPType` enum. - We map them to properties via the `FPProperties` trait. - We map from C++ type to `FPType` in the `getFPType` function so logic is easier to understand and extend. --- libc/src/__support/FPUtil/FloatProperties.h | 125 +++++++------------- libc/src/__support/FPUtil/dyadic_float.h | 8 +- 2 files changed, 48 insertions(+), 85 deletions(-) diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h index 9d91688e023e9..b91e7ace5233f 100644 --- a/libc/src/__support/FPUtil/FloatProperties.h +++ b/libc/src/__support/FPUtil/FloatProperties.h @@ -17,12 +17,18 @@ namespace LIBC_NAMESPACE { namespace fputil { -template struct FloatProperties {}; +// The supported floating point types. +enum class FPType { + IEEE754_Binary16, + IEEE754_Binary32, + IEEE754_Binary64, + IEEE754_Binary128, + X86_Binary80, +}; -template <> struct FloatProperties { +template struct FPProperties {}; +template <> struct FPProperties { typedef uint32_t BitsType; - static_assert(sizeof(BitsType) == sizeof(float), - "Unexpected size of 'float' type."); static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8; @@ -46,10 +52,8 @@ template <> struct FloatProperties { static constexpr BitsType QUIET_NAN_MASK = 0x00400000U; }; -template <> struct FloatProperties { +template <> struct FPProperties { typedef uint64_t BitsType; - static_assert(sizeof(BitsType) == sizeof(double), - "Unexpected size of 'double' type."); static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8; @@ -72,47 +76,10 @@ template <> struct FloatProperties { static constexpr BitsType QUIET_NAN_MASK = 0x0008000000000000ULL; }; -#if defined(LONG_DOUBLE_IS_DOUBLE) -// Properties for numbers represented in 64 bits long double on Windows -// platform. -template <> struct FloatProperties { - typedef uint64_t BitsType; - static_assert(sizeof(BitsType) == sizeof(double), - "Unexpected size of 'double' type."); - - static constexpr uint32_t BIT_WIDTH = FloatProperties::BIT_WIDTH; - - static constexpr uint32_t MANTISSA_WIDTH = - FloatProperties::MANTISSA_WIDTH; - static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1; - static constexpr uint32_t EXPONENT_WIDTH = - FloatProperties::EXPONENT_WIDTH; - static constexpr BitsType MANTISSA_MASK = - FloatProperties::MANTISSA_MASK; - static constexpr BitsType SIGN_MASK = FloatProperties::SIGN_MASK; - static constexpr BitsType EXPONENT_MASK = - FloatProperties::EXPONENT_MASK; - static constexpr uint32_t EXPONENT_BIAS = - FloatProperties::EXPONENT_BIAS; - - static constexpr BitsType EXP_MANT_MASK = - FloatProperties::EXP_MANT_MASK; - static_assert(EXP_MANT_MASK == ~SIGN_MASK, - "Exponent and mantissa masks are not as expected."); - - // If a number x is a NAN, then it is a quiet NAN if: - // QuietNaNMask & bits(x) != 0 - // Else, it is a signalling NAN. - static constexpr BitsType QUIET_NAN_MASK = - FloatProperties::QUIET_NAN_MASK; -}; -#elif defined(SPECIAL_X86_LONG_DOUBLE) // Properties for numbers represented in 80 bits long double on non-Windows x86 // platforms. -template <> struct FloatProperties { +template <> struct FPProperties { typedef UInt128 BitsType; - static_assert(sizeof(BitsType) == sizeof(long double), - "Unexpected size of 'long double' type."); static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) * 8) - 48; static constexpr BitsType FULL_WIDTH_MASK = ((BitsType(1) << BIT_WIDTH) - 1); @@ -143,13 +110,11 @@ template <> struct FloatProperties { static constexpr BitsType QUIET_NAN_MASK = BitsType(1) << (MANTISSA_WIDTH - 1); }; -#else + // Properties for numbers represented in 128 bits long double on non x86 // platform. -template <> struct FloatProperties { +template <> struct FPProperties { typedef UInt128 BitsType; - static_assert(sizeof(BitsType) == sizeof(long double), - "Unexpected size of 'long double' type."); static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; @@ -172,39 +137,39 @@ template <> struct FloatProperties { static constexpr BitsType QUIET_NAN_MASK = BitsType(1) << (MANTISSA_WIDTH - 1); }; -#endif -#if (defined(LIBC_COMPILER_HAS_FLOAT128) && \ - !defined(LIBC_FLOAT128_IS_LONG_DOUBLE)) -// Properties for numbers represented in 128 bits long double on non x86 -// platform. -template <> struct FloatProperties { - typedef UInt128 BitsType; - static_assert(sizeof(BitsType) == sizeof(float128), - "Unexpected size of 'float128' type."); - - static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; - - static constexpr uint32_t MANTISSA_WIDTH = 112; - static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1; - static constexpr uint32_t EXPONENT_WIDTH = 15; - static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1; - static constexpr BitsType SIGN_MASK = BitsType(1) - << (EXPONENT_WIDTH + MANTISSA_WIDTH); - static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); - static constexpr uint32_t EXPONENT_BIAS = 16383; - - static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK; - static_assert(EXP_MANT_MASK == ~SIGN_MASK, - "Exponent and mantissa masks are not as expected."); +//----------------------------------------------------------------------------- +template static constexpr FPType getFPType() { + if constexpr (cpp::is_same_v && __FLT_MANT_DIG__ == 24) + return FPType::IEEE754_Binary32; + else if constexpr (cpp::is_same_v && __DBL_MANT_DIG__ == 53) + return FPType::IEEE754_Binary64; + else if constexpr (cpp::is_same_v) { + if constexpr (__LDBL_MANT_DIG__ == 53) + return FPType::IEEE754_Binary64; + else if constexpr (__LDBL_MANT_DIG__ == 64) + return FPType::X86_Binary80; + else if constexpr (__LDBL_MANT_DIG__ == 113) + return FPType::IEEE754_Binary128; + } +#if defined(LIBC_COMPILER_HAS_C23_FLOAT16) + else if constexpr (cpp::is_same_v) + return FPType::IEEE754_Binary16; +#endif +#if defined(LIBC_COMPILER_HAS_C23_FLOAT128) + else if constexpr (cpp::is_same_v) + return FPType::IEEE754_Binary128; +#endif +#if defined(LIBC_COMPILER_HAS_FLOAT128_EXTENSION) + else if constexpr (cpp::is_same_v) + return FPType::IEEE754_Binary128; +#endif + else + static_assert(cpp::always_false, "Unsupported type"); +} - // If a number x is a NAN, then it is a quiet NAN if: - // QuietNaNMask & bits(x) != 0 - // Else, it is a signalling NAN. - static constexpr BitsType QUIET_NAN_MASK = BitsType(1) - << (MANTISSA_WIDTH - 1); -}; -#endif // LIBC_COMPILER_HAS_FLOAT128 +template +struct FloatProperties : public FPProperties()> {}; } // namespace fputil } // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h index 2ee97b4ac7f78..b7920943804e6 100644 --- a/libc/src/__support/FPUtil/dyadic_float.h +++ b/libc/src/__support/FPUtil/dyadic_float.h @@ -38,13 +38,11 @@ template struct DyadicFloat { int exponent = 0; MantissaType mantissa = MantissaType(0); - DyadicFloat() = default; + constexpr DyadicFloat() = default; - template && - (FloatProperties::MANTISSA_WIDTH < Bits), - int> = 0> + template , int> = 0> DyadicFloat(T x) { + static_assert(FloatProperties::MANTISSA_WIDTH < Bits); FPBits x_bits(x); sign = x_bits.get_sign(); exponent = x_bits.get_exponent() - FloatProperties::MANTISSA_WIDTH; From 4c2c55c1a31b528933b2bfbee61efb0aa0aa30bc Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 27 Nov 2023 15:30:17 +0000 Subject: [PATCH 4/4] Fix function case --- libc/src/__support/FPUtil/FloatProperties.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h index b91e7ace5233f..0e65a60ac6548 100644 --- a/libc/src/__support/FPUtil/FloatProperties.h +++ b/libc/src/__support/FPUtil/FloatProperties.h @@ -139,7 +139,7 @@ template <> struct FPProperties { }; //----------------------------------------------------------------------------- -template static constexpr FPType getFPType() { +template static constexpr FPType get_fp_type() { if constexpr (cpp::is_same_v && __FLT_MANT_DIG__ == 24) return FPType::IEEE754_Binary32; else if constexpr (cpp::is_same_v && __DBL_MANT_DIG__ == 53) @@ -169,7 +169,7 @@ template static constexpr FPType getFPType() { } template -struct FloatProperties : public FPProperties()> {}; +struct FloatProperties : public FPProperties()> {}; } // namespace fputil } // namespace LIBC_NAMESPACE