diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 36df9c54c4777..6743fee9b1a48 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -57,6 +57,11 @@ template struct FPBits { UIntType get_mantissa() const { return bits & FloatProp::MANTISSA_MASK; } + // The function return mantissa with implicit bit set for normal values. + constexpr UIntType get_explicit_mantissa() { + return (FloatProp::MANTISSA_MASK + 1) | (FloatProp::MANTISSA_MASK & bits); + } + void set_unbiased_exponent(UIntType expVal) { expVal = (expVal << (FloatProp::MANTISSA_WIDTH)) & FloatProp::EXPONENT_MASK; bits &= ~(FloatProp::EXPONENT_MASK); @@ -69,14 +74,12 @@ template struct FPBits { } void set_sign(bool signVal) { - bits &= ~(FloatProp::SIGN_MASK); - UIntType sign = UIntType(signVal) << (FloatProp::BIT_WIDTH - 1); - bits |= sign; + bits |= FloatProp::SIGN_MASK; + if (!signVal) + bits -= FloatProp::SIGN_MASK; } - bool get_sign() const { - return ((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1)); - } + bool get_sign() const { return (bits & FloatProp::SIGN_MASK) != 0; } static_assert(sizeof(T) == sizeof(UIntType), "Data type and integral representation have different sizes."); @@ -92,7 +95,7 @@ template struct FPBits { static constexpr UIntType MAX_NORMAL = ((UIntType(MAX_EXPONENT) - 1) << MantissaWidth::VALUE) | MAX_SUBNORMAL; - // We don't want accidental type promotions/conversions so we require exact + // We don't want accidental type promotions/conversions, so we require exact // type match. template ::Value, int> = 0> @@ -118,38 +121,41 @@ template struct FPBits { } bool is_zero() const { - return get_mantissa() == 0 && get_unbiased_exponent() == 0; + // Remove sign bit by shift + return (bits << 1) == 0; } bool is_inf() const { - return get_mantissa() == 0 && get_unbiased_exponent() == MAX_EXPONENT; + return (bits & FloatProp::EXP_MANT_MASK) == FloatProp::EXPONENT_MASK; } bool is_nan() const { - return get_unbiased_exponent() == MAX_EXPONENT && get_mantissa() != 0; + return (bits & FloatProp::EXP_MANT_MASK) > FloatProp::EXPONENT_MASK; } - bool is_inf_or_nan() const { return get_unbiased_exponent() == MAX_EXPONENT; } - - static FPBits zero() { return FPBits(); } + bool is_inf_or_nan() const { + return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK; + } - static FPBits neg_zero() { - return FPBits(UIntType(1) << (sizeof(UIntType) * 8 - 1)); + static constexpr FPBits zero(bool sign = false) { + return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0)); } - static FPBits inf() { + static constexpr FPBits neg_zero() { return zero(true); } + + static constexpr FPBits inf() { FPBits bits; bits.set_unbiased_exponent(MAX_EXPONENT); return bits; } - static FPBits neg_inf() { + static constexpr FPBits neg_inf() { FPBits bits = inf(); bits.set_sign(1); return bits; } - static T build_nan(UIntType v) { + static constexpr T build_nan(UIntType v) { FPBits bits = inf(); bits.set_mantissa(v); return T(bits); diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h index 8cf0da1267a91..ad52a4066e1e6 100644 --- a/libc/src/__support/FPUtil/FloatProperties.h +++ b/libc/src/__support/FPUtil/FloatProperties.h @@ -22,7 +22,7 @@ template <> struct FloatProperties { static_assert(sizeof(BitsType) == sizeof(float), "Unexpected size of 'float' type."); - static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; + static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8; static constexpr uint32_t MANTISSA_WIDTH = 23; static constexpr uint32_t EXPONENT_WIDTH = 8; @@ -32,6 +32,10 @@ template <> struct FloatProperties { static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); static constexpr uint32_t EXPONENT_BIAS = 127; + 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."); + // If a number x is a NAN, then it is a quiet NAN if: // QuietNaNMask & bits(x) != 0 // Else, it is a signalling NAN. @@ -43,7 +47,7 @@ template <> struct FloatProperties { static_assert(sizeof(BitsType) == sizeof(double), "Unexpected size of 'double' type."); - static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3; + static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8; static constexpr uint32_t MANTISSA_WIDTH = 52; static constexpr uint32_t EXPONENT_WIDTH = 11; @@ -53,6 +57,10 @@ template <> struct FloatProperties { static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK); static constexpr uint32_t EXPONENT_BIAS = 1023; + 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."); + // If a number x is a NAN, then it is a quiet NAN if: // QuietNaNMask & bits(x) != 0 // Else, it is a signalling NAN. @@ -95,7 +103,7 @@ template <> struct FloatProperties { static_assert(sizeof(BitsType) == sizeof(long double), "Unexpected size of 'long double' type."); - static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) << 3) - 48; + static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) * 8) - 48; static constexpr uint32_t MANTISSA_WIDTH = 63; static constexpr uint32_t EXPONENT_WIDTH = 15;