forked from OSchip/llvm-project
[libc][math] Improved FBits performance and readablity.
Some function added in preparation to fmod commit. Differential Revision: https://reviews.llvm.org/D127097
This commit is contained in:
parent
f93dee1033
commit
b03567fe2b
|
@ -57,6 +57,11 @@ template <typename T> 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 <typename T> 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 <typename T> struct FPBits {
|
|||
static constexpr UIntType MAX_NORMAL =
|
||||
((UIntType(MAX_EXPONENT) - 1) << MantissaWidth<T>::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 <typename XType,
|
||||
cpp::EnableIfType<cpp::IsSame<T, XType>::Value, int> = 0>
|
||||
|
@ -118,38 +121,41 @@ template <typename T> 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<T> zero() { return FPBits(); }
|
||||
|
||||
static FPBits<T> neg_zero() {
|
||||
return FPBits(UIntType(1) << (sizeof(UIntType) * 8 - 1));
|
||||
bool is_inf_or_nan() const {
|
||||
return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK;
|
||||
}
|
||||
|
||||
static FPBits<T> inf() {
|
||||
static constexpr FPBits<T> zero(bool sign = false) {
|
||||
return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0));
|
||||
}
|
||||
|
||||
static constexpr FPBits<T> neg_zero() { return zero(true); }
|
||||
|
||||
static constexpr FPBits<T> inf() {
|
||||
FPBits<T> bits;
|
||||
bits.set_unbiased_exponent(MAX_EXPONENT);
|
||||
return bits;
|
||||
}
|
||||
|
||||
static FPBits<T> neg_inf() {
|
||||
static constexpr FPBits<T> neg_inf() {
|
||||
FPBits<T> bits = inf();
|
||||
bits.set_sign(1);
|
||||
return bits;
|
||||
}
|
||||
|
||||
static T build_nan(UIntType v) {
|
||||
static constexpr T build_nan(UIntType v) {
|
||||
FPBits<T> bits = inf();
|
||||
bits.set_mantissa(v);
|
||||
return T(bits);
|
||||
|
|
|
@ -22,7 +22,7 @@ template <> struct FloatProperties<float> {
|
|||
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<float> {
|
|||
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<double> {
|
|||
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<double> {
|
|||
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<long double> {
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue