diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h index 9d91688e023e9..0e65a60ac6548 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 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) + 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; diff --git a/libc/src/__support/macros/properties/float.h b/libc/src/__support/macros/properties/float.h index 3bfd041568936..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 >= 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