mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 08:02:08 +00:00
[libc] Make FPBits a union.
This helps us avoid the uncomfortable reinterpret-casts. Avoiding the reinterpret casts prevents us from tripping the sanitizers as well. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D100360
This commit is contained in:
parent
f1a4df542d
commit
6666e0d7a2
@ -23,7 +23,7 @@ ValuesEqual(T x1, T x2) {
|
||||
return bits2.isNaN() && bits2.isNaN();
|
||||
|
||||
// For all other values, we want the values to be bitwise equal.
|
||||
return bits1.bitsAsUInt() == bits2.bitsAsUInt();
|
||||
return bits1.uintval() == bits2.uintval();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -43,6 +43,6 @@ void RemQuoDiff(RemQuoFunc<T> func1, RemQuoFunc<T> func2, const uint8_t *data,
|
||||
|
||||
__llvm_libc::fputil::FPBits<T> bits1(remainder1);
|
||||
__llvm_libc::fputil::FPBits<T> bits2(remainder2);
|
||||
if (bits1.bitsAsUInt() != bits2.bitsAsUInt())
|
||||
if (bits1.uintval() != bits2.uintval())
|
||||
__builtin_trap();
|
||||
}
|
||||
|
@ -44,17 +44,17 @@ LLVM_LIBC_FUNCTION(float, fmaf, (float x, float y, float z)) {
|
||||
// bit of sum, so that the sticky bits used when rounding sum to float are
|
||||
// correct (when it matters).
|
||||
fputil::FPBits<double> t(
|
||||
(bit_prod.exponent >= bitz.exponent)
|
||||
? ((static_cast<double>(bit_sum) - bit_prod) - bitz)
|
||||
: ((static_cast<double>(bit_sum) - bitz) - bit_prod));
|
||||
(bit_prod.encoding.exponent >= bitz.encoding.exponent)
|
||||
? ((double(bit_sum) - double(bit_prod)) - double(bitz))
|
||||
: ((double(bit_sum) - double(bitz)) - double(bit_prod)));
|
||||
|
||||
// Update sticky bits if t != 0.0 and the least (52 - 23 - 1 = 28) bits are
|
||||
// zero.
|
||||
if (!t.isZero() && ((bit_sum.mantissa & 0xfff'ffffULL) == 0)) {
|
||||
if (bit_sum.sign != t.sign) {
|
||||
++bit_sum.mantissa;
|
||||
} else if (bit_sum.mantissa) {
|
||||
--bit_sum.mantissa;
|
||||
if (!t.isZero() && ((bit_sum.encoding.mantissa & 0xfff'ffffULL) == 0)) {
|
||||
if (bit_sum.encoding.sign != t.encoding.sign) {
|
||||
++bit_sum.encoding.mantissa;
|
||||
} else if (bit_sum.encoding.mantissa) {
|
||||
--bit_sum.encoding.mantissa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ public:
|
||||
FPBits resultBits(result);
|
||||
ASSERT_FALSE(resultBits.isZero());
|
||||
// Verify that the result is indeed subnormal.
|
||||
ASSERT_EQ(resultBits.exponent, uint16_t(0));
|
||||
ASSERT_EQ(resultBits.encoding.exponent, uint16_t(0));
|
||||
// But if the exp is so less that normalization leads to zero, then
|
||||
// the result should be zero.
|
||||
result = func(x, -FPBits::maxExponent - int(mantissaWidth) - 5);
|
||||
|
@ -163,25 +163,31 @@ public:
|
||||
result = func(x, 0);
|
||||
FPBits xBits = FPBits(x);
|
||||
FPBits resultBits = FPBits(result);
|
||||
ASSERT_EQ(resultBits.exponent, uint16_t(xBits.exponent - 1));
|
||||
ASSERT_EQ(resultBits.mantissa, (UIntType(1) << MantissaWidth::value) - 1);
|
||||
ASSERT_EQ(resultBits.encoding.exponent,
|
||||
uint16_t(xBits.encoding.exponent - 1));
|
||||
ASSERT_EQ(resultBits.encoding.mantissa,
|
||||
(UIntType(1) << MantissaWidth::value) - 1);
|
||||
|
||||
result = func(x, T(33.0));
|
||||
resultBits = FPBits(result);
|
||||
ASSERT_EQ(resultBits.exponent, xBits.exponent);
|
||||
ASSERT_EQ(resultBits.mantissa, xBits.mantissa + UIntType(1));
|
||||
ASSERT_EQ(resultBits.encoding.exponent, xBits.encoding.exponent);
|
||||
ASSERT_EQ(resultBits.encoding.mantissa,
|
||||
xBits.encoding.mantissa + UIntType(1));
|
||||
|
||||
x = -x;
|
||||
|
||||
result = func(x, 0);
|
||||
resultBits = FPBits(result);
|
||||
ASSERT_EQ(resultBits.exponent, uint16_t(xBits.exponent - 1));
|
||||
ASSERT_EQ(resultBits.mantissa, (UIntType(1) << MantissaWidth::value) - 1);
|
||||
ASSERT_EQ(resultBits.encoding.exponent,
|
||||
uint16_t(xBits.encoding.exponent - 1));
|
||||
ASSERT_EQ(resultBits.encoding.mantissa,
|
||||
(UIntType(1) << MantissaWidth::value) - 1);
|
||||
|
||||
result = func(x, T(-33.0));
|
||||
resultBits = FPBits(result);
|
||||
ASSERT_EQ(resultBits.exponent, xBits.exponent);
|
||||
ASSERT_EQ(resultBits.mantissa, xBits.mantissa + UIntType(1));
|
||||
ASSERT_EQ(resultBits.encoding.exponent, xBits.encoding.exponent);
|
||||
ASSERT_EQ(resultBits.encoding.mantissa,
|
||||
xBits.encoding.mantissa + UIntType(1));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -135,9 +135,9 @@ public:
|
||||
// We start with 1.0 so that the implicit bit for x86 long doubles
|
||||
// is set.
|
||||
FPBits bits(F(1.0));
|
||||
bits.exponent = exponentLimit + FPBits::exponentBias;
|
||||
bits.sign = 1;
|
||||
bits.mantissa = 0;
|
||||
bits.encoding.exponent = exponentLimit + FPBits::exponentBias;
|
||||
bits.encoding.sign = 1;
|
||||
bits.encoding.mantissa = 0;
|
||||
|
||||
F x = bits;
|
||||
long mpfrResult;
|
||||
@ -199,10 +199,10 @@ public:
|
||||
// We start with 1.0 so that the implicit bit for x86 long doubles
|
||||
// is set.
|
||||
FPBits bits(F(1.0));
|
||||
bits.exponent = exponentLimit + FPBits::exponentBias;
|
||||
bits.sign = 1;
|
||||
bits.mantissa = UIntType(0x1)
|
||||
<< (__llvm_libc::fputil::MantissaWidth<F>::value - 1);
|
||||
bits.encoding.exponent = exponentLimit + FPBits::exponentBias;
|
||||
bits.encoding.sign = 1;
|
||||
bits.encoding.mantissa =
|
||||
UIntType(0x1) << (__llvm_libc::fputil::MantissaWidth<F>::value - 1);
|
||||
|
||||
F x = bits;
|
||||
if (TestModes) {
|
||||
|
@ -37,7 +37,7 @@ TEST(LlvmLibcSqrtTest, SpecialValues) {
|
||||
TEST(LlvmLibcSqrtTest, DenormalValues) {
|
||||
for (UIntType mant = 1; mant < HiddenBit; mant <<= 1) {
|
||||
FPBits denormal(0.0);
|
||||
denormal.mantissa = mant;
|
||||
denormal.encoding.mantissa = mant;
|
||||
|
||||
ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, double(denormal),
|
||||
__llvm_libc::sqrt(denormal), 0.5);
|
||||
|
@ -37,7 +37,7 @@ TEST(LlvmLibcSqrtfTest, SpecialValues) {
|
||||
TEST(LlvmLibcSqrtfTest, DenormalValues) {
|
||||
for (UIntType mant = 1; mant < HiddenBit; mant <<= 1) {
|
||||
FPBits denormal(0.0f);
|
||||
denormal.mantissa = mant;
|
||||
denormal.encoding.mantissa = mant;
|
||||
|
||||
ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, float(denormal),
|
||||
__llvm_libc::sqrtf(denormal), 0.5);
|
||||
|
@ -37,7 +37,7 @@ TEST(LlvmLibcSqrtlTest, SpecialValues) {
|
||||
TEST(LlvmLibcSqrtlTest, DenormalValues) {
|
||||
for (UIntType mant = 1; mant < HiddenBit; mant <<= 1) {
|
||||
FPBits denormal(0.0L);
|
||||
denormal.mantissa = mant;
|
||||
denormal.encoding.mantissa = mant;
|
||||
|
||||
ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, static_cast<long double>(denormal),
|
||||
__llvm_libc::sqrtl(denormal), 0.5);
|
||||
|
@ -20,7 +20,7 @@ template <typename T,
|
||||
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
|
||||
static inline T abs(T x) {
|
||||
FPBits<T> bits(x);
|
||||
bits.sign = 0;
|
||||
bits.encoding.sign = 0;
|
||||
return T(bits);
|
||||
}
|
||||
|
||||
@ -33,11 +33,11 @@ static inline T fmin(T x, T y) {
|
||||
return y;
|
||||
} else if (bity.isNaN()) {
|
||||
return x;
|
||||
} else if (bitx.sign != bity.sign) {
|
||||
} else if (bitx.encoding.sign != bity.encoding.sign) {
|
||||
// To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and
|
||||
// y has different signs and both are not NaNs, we return the number
|
||||
// with negative sign.
|
||||
return (bitx.sign ? x : y);
|
||||
return (bitx.encoding.sign ? x : y);
|
||||
} else {
|
||||
return (x < y ? x : y);
|
||||
}
|
||||
@ -52,11 +52,11 @@ static inline T fmax(T x, T y) {
|
||||
return y;
|
||||
} else if (bity.isNaN()) {
|
||||
return x;
|
||||
} else if (bitx.sign != bity.sign) {
|
||||
} else if (bitx.encoding.sign != bity.encoding.sign) {
|
||||
// To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and
|
||||
// y has different signs and both are not NaNs, we return the number
|
||||
// with positive sign.
|
||||
return (bitx.sign ? y : x);
|
||||
return (bitx.encoding.sign ? y : x);
|
||||
} else {
|
||||
return (x > y ? x : y);
|
||||
}
|
||||
|
@ -43,12 +43,12 @@ static inline T remquo(T x, T y, int &q) {
|
||||
return x;
|
||||
}
|
||||
|
||||
bool resultSign = (xbits.sign == ybits.sign ? false : true);
|
||||
bool resultSign = (xbits.encoding.sign == ybits.encoding.sign ? false : true);
|
||||
|
||||
// Once we know the sign of the result, we can just operate on the absolute
|
||||
// values. The correct sign can be applied to the result after the result
|
||||
// is evaluated.
|
||||
xbits.sign = ybits.sign = 0;
|
||||
xbits.encoding.sign = ybits.encoding.sign = 0;
|
||||
|
||||
NormalFloat<T> normalx(xbits), normaly(ybits);
|
||||
int exp = normalx.exponent - normaly.exponent;
|
||||
|
@ -57,7 +57,7 @@ template <> struct FPUIntType<long double> { using Type = __uint128_t; };
|
||||
// floating numbers. On x86 platforms however, the 'long double' type maps to
|
||||
// an x87 floating point format. This format is an IEEE 754 extension format.
|
||||
// It is handled as an explicit specialization of this class.
|
||||
template <typename T> struct __attribute__((packed)) FPBits {
|
||||
template <typename T> union FPBits {
|
||||
static_assert(cpp::IsFloatingPointType<T>::Value,
|
||||
"FPBits instantiated with invalid type.");
|
||||
|
||||
@ -66,9 +66,18 @@ template <typename T> struct __attribute__((packed)) FPBits {
|
||||
// type is provided for such reinterpretations.
|
||||
using UIntType = typename FPUIntType<T>::Type;
|
||||
|
||||
UIntType mantissa : MantissaWidth<T>::value;
|
||||
uint16_t exponent : ExponentWidth<T>::value;
|
||||
uint8_t sign : 1;
|
||||
struct __attribute__((packed)) {
|
||||
UIntType mantissa : MantissaWidth<T>::value;
|
||||
uint16_t exponent : ExponentWidth<T>::value;
|
||||
uint8_t sign : 1;
|
||||
} encoding;
|
||||
UIntType integer;
|
||||
T val;
|
||||
|
||||
static_assert(sizeof(encoding) == sizeof(UIntType),
|
||||
"Encoding and integral representation have different sizes.");
|
||||
static_assert(sizeof(integer) == sizeof(UIntType),
|
||||
"Integral representation and value type have different sizes.");
|
||||
|
||||
static constexpr int exponentBias = (1 << (ExponentWidth<T>::value - 1)) - 1;
|
||||
static constexpr int maxExponent = (1 << ExponentWidth<T>::value) - 1;
|
||||
@ -84,60 +93,56 @@ template <typename T> struct __attribute__((packed)) FPBits {
|
||||
// We don't want accidental type promotions/conversions so we require exact
|
||||
// type match.
|
||||
template <typename XType,
|
||||
cpp::EnableIfType<cpp::IsSame<T, XType>::Value ||
|
||||
(cpp::IsIntegral<XType>::Value &&
|
||||
(sizeof(XType) == sizeof(UIntType))),
|
||||
int> = 0>
|
||||
explicit FPBits(XType x) {
|
||||
*this = *reinterpret_cast<FPBits<T> *>(&x);
|
||||
cpp::EnableIfType<cpp::IsSame<T, XType>::Value, int> = 0>
|
||||
explicit FPBits(XType x) : val(x) {}
|
||||
|
||||
template <typename XType,
|
||||
cpp::EnableIfType<cpp::IsSame<XType, UIntType>::Value, int> = 0>
|
||||
explicit FPBits(XType x) : integer(x) {}
|
||||
|
||||
FPBits() : integer(0) {}
|
||||
|
||||
operator T() { return val; }
|
||||
|
||||
UIntType uintval() const { return integer; }
|
||||
|
||||
int getExponent() const { return int(encoding.exponent) - exponentBias; }
|
||||
|
||||
bool isZero() const {
|
||||
return encoding.mantissa == 0 && encoding.exponent == 0;
|
||||
}
|
||||
|
||||
operator T() { return *reinterpret_cast<T *>(this); }
|
||||
|
||||
int getExponent() const { return int(exponent) - exponentBias; }
|
||||
|
||||
bool isZero() const { return mantissa == 0 && exponent == 0; }
|
||||
|
||||
bool isInf() const { return mantissa == 0 && exponent == maxExponent; }
|
||||
|
||||
bool isNaN() const { return exponent == maxExponent && mantissa != 0; }
|
||||
|
||||
bool isInfOrNaN() const { return exponent == maxExponent; }
|
||||
|
||||
// Methods below this are used by tests.
|
||||
// The to and from integer bits converters are only used in tests. Hence,
|
||||
// the potential software implementations of UIntType will not slow real
|
||||
// code.
|
||||
|
||||
UIntType bitsAsUInt() const {
|
||||
return *reinterpret_cast<const UIntType *>(this);
|
||||
bool isInf() const {
|
||||
return encoding.mantissa == 0 && encoding.exponent == maxExponent;
|
||||
}
|
||||
|
||||
static FPBits<T> zero() { return FPBits(T(0.0)); }
|
||||
bool isNaN() const {
|
||||
return encoding.exponent == maxExponent && encoding.mantissa != 0;
|
||||
}
|
||||
|
||||
bool isInfOrNaN() const { return encoding.exponent == maxExponent; }
|
||||
|
||||
static FPBits<T> zero() { return FPBits(); }
|
||||
|
||||
static FPBits<T> negZero() {
|
||||
FPBits<T> bits(T(0.0));
|
||||
bits.sign = 1;
|
||||
return bits;
|
||||
return FPBits(UIntType(1) << (sizeof(UIntType) * 8 - 1));
|
||||
}
|
||||
|
||||
static FPBits<T> inf() {
|
||||
FPBits<T> bits(T(0.0));
|
||||
bits.exponent = maxExponent;
|
||||
FPBits<T> bits;
|
||||
bits.encoding.exponent = maxExponent;
|
||||
return bits;
|
||||
}
|
||||
|
||||
static FPBits<T> negInf() {
|
||||
FPBits<T> bits(T(0.0));
|
||||
bits.exponent = maxExponent;
|
||||
bits.sign = 1;
|
||||
FPBits<T> bits = inf();
|
||||
bits.encoding.sign = 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
static T buildNaN(UIntType v) {
|
||||
FPBits<T> bits(T(0.0));
|
||||
bits.exponent = maxExponent;
|
||||
bits.mantissa = v;
|
||||
FPBits<T> bits = inf();
|
||||
bits.encoding.mantissa = v;
|
||||
return bits;
|
||||
}
|
||||
};
|
||||
|
@ -139,26 +139,27 @@ static inline T hypot(T x, T y) {
|
||||
DUIntType a_mant_sq, b_mant_sq;
|
||||
bool sticky_bits;
|
||||
|
||||
if ((x_bits.exponent >= y_bits.exponent + MantissaWidth<T>::value + 2) ||
|
||||
if ((x_bits.encoding.exponent >=
|
||||
y_bits.encoding.exponent + MantissaWidth<T>::value + 2) ||
|
||||
(y == 0)) {
|
||||
return abs(x);
|
||||
} else if ((y_bits.exponent >=
|
||||
x_bits.exponent + MantissaWidth<T>::value + 2) ||
|
||||
} else if ((y_bits.encoding.exponent >=
|
||||
x_bits.encoding.exponent + MantissaWidth<T>::value + 2) ||
|
||||
(x == 0)) {
|
||||
y_bits.sign = 0;
|
||||
y_bits.encoding.sign = 0;
|
||||
return abs(y);
|
||||
}
|
||||
|
||||
if (x >= y) {
|
||||
a_exp = x_bits.exponent;
|
||||
a_mant = x_bits.mantissa;
|
||||
b_exp = y_bits.exponent;
|
||||
b_mant = y_bits.mantissa;
|
||||
a_exp = x_bits.encoding.exponent;
|
||||
a_mant = x_bits.encoding.mantissa;
|
||||
b_exp = y_bits.encoding.exponent;
|
||||
b_mant = y_bits.encoding.mantissa;
|
||||
} else {
|
||||
a_exp = y_bits.exponent;
|
||||
a_mant = y_bits.mantissa;
|
||||
b_exp = x_bits.exponent;
|
||||
b_mant = x_bits.mantissa;
|
||||
a_exp = y_bits.encoding.exponent;
|
||||
a_mant = y_bits.encoding.mantissa;
|
||||
b_exp = x_bits.encoding.exponent;
|
||||
b_mant = x_bits.encoding.mantissa;
|
||||
}
|
||||
|
||||
out_exp = a_exp;
|
||||
|
@ -28,7 +28,7 @@ template <> struct Padding<4> { static constexpr unsigned value = 16; };
|
||||
// x86_64 padding.
|
||||
template <> struct Padding<8> { static constexpr unsigned value = 48; };
|
||||
|
||||
template <> struct __attribute__((packed)) FPBits<long double> {
|
||||
template <> union FPBits<long double> {
|
||||
using UIntType = __uint128_t;
|
||||
|
||||
static constexpr int exponentBias = 0x3FFF;
|
||||
@ -43,102 +43,97 @@ template <> struct __attribute__((packed)) FPBits<long double> {
|
||||
((UIntType(maxExponent) - 1) << (MantissaWidth<long double>::value + 1)) |
|
||||
(UIntType(1) << MantissaWidth<long double>::value) | maxSubnormal;
|
||||
|
||||
UIntType mantissa : MantissaWidth<long double>::value;
|
||||
uint8_t implicitBit : 1;
|
||||
uint16_t exponent : ExponentWidth<long double>::value;
|
||||
uint8_t sign : 1;
|
||||
uint64_t padding : Padding<sizeof(uintptr_t)>::value;
|
||||
struct __attribute__((packed)) {
|
||||
UIntType mantissa : MantissaWidth<long double>::value;
|
||||
uint8_t implicitBit : 1;
|
||||
uint16_t exponent : ExponentWidth<long double>::value;
|
||||
uint8_t sign : 1;
|
||||
uint64_t padding : Padding<sizeof(uintptr_t)>::value;
|
||||
} encoding;
|
||||
UIntType integer;
|
||||
long double val;
|
||||
|
||||
FPBits() : integer(0) {}
|
||||
|
||||
template <typename XType,
|
||||
cpp::EnableIfType<cpp::IsSame<long double, XType>::Value, int> = 0>
|
||||
explicit FPBits<long double>(XType x) {
|
||||
*this = *reinterpret_cast<FPBits<long double> *>(&x);
|
||||
explicit FPBits<long double>(XType x) : val(x) {}
|
||||
|
||||
template <typename XType,
|
||||
cpp::EnableIfType<cpp::IsSame<XType, UIntType>::Value, int> = 0>
|
||||
explicit FPBits(XType x) : integer(x) {}
|
||||
|
||||
operator long double() { return val; }
|
||||
|
||||
UIntType uintval() {
|
||||
// We zero the padding bits as they can contain garbage.
|
||||
static constexpr UIntType mask =
|
||||
(UIntType(1) << (sizeof(long double) * 8 -
|
||||
Padding<sizeof(uintptr_t)>::value)) -
|
||||
1;
|
||||
return integer & mask;
|
||||
}
|
||||
|
||||
operator long double() { return *reinterpret_cast<long double *>(this); }
|
||||
|
||||
int getExponent() const {
|
||||
if (exponent == 0)
|
||||
if (encoding.exponent == 0)
|
||||
return int(1) - exponentBias;
|
||||
return int(exponent) - exponentBias;
|
||||
return int(encoding.exponent) - exponentBias;
|
||||
}
|
||||
|
||||
bool isZero() const {
|
||||
return exponent == 0 && mantissa == 0 && implicitBit == 0;
|
||||
return encoding.exponent == 0 && encoding.mantissa == 0 &&
|
||||
encoding.implicitBit == 0;
|
||||
}
|
||||
|
||||
bool isInf() const {
|
||||
return exponent == maxExponent && mantissa == 0 && implicitBit == 1;
|
||||
return encoding.exponent == maxExponent && encoding.mantissa == 0 &&
|
||||
encoding.implicitBit == 1;
|
||||
}
|
||||
|
||||
bool isNaN() const {
|
||||
if (exponent == maxExponent) {
|
||||
return (implicitBit == 0) || mantissa != 0;
|
||||
} else if (exponent != 0) {
|
||||
return implicitBit == 0;
|
||||
if (encoding.exponent == maxExponent) {
|
||||
return (encoding.implicitBit == 0) || encoding.mantissa != 0;
|
||||
} else if (encoding.exponent != 0) {
|
||||
return encoding.implicitBit == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isInfOrNaN() const {
|
||||
return (exponent == maxExponent) || (exponent != 0 && implicitBit == 0);
|
||||
return (encoding.exponent == maxExponent) ||
|
||||
(encoding.exponent != 0 && encoding.implicitBit == 0);
|
||||
}
|
||||
|
||||
// Methods below this are used by tests.
|
||||
|
||||
template <typename XType,
|
||||
cpp::EnableIfType<cpp::IsSame<UIntType, XType>::Value, int> = 0>
|
||||
explicit FPBits<long double>(XType x) {
|
||||
// The last 4 bytes of v are ignored in case of i386.
|
||||
*this = *reinterpret_cast<FPBits<long double> *>(&x);
|
||||
}
|
||||
|
||||
UIntType bitsAsUInt() const {
|
||||
// We cannot just return the bits as is as it will lead to reading
|
||||
// out of bounds in case of i386. So, we first copy the wider value
|
||||
// before returning the value. This makes the last 4 bytes are always
|
||||
// zero in case i386.
|
||||
UIntType result = UIntType(0);
|
||||
*reinterpret_cast<FPBits<long double> *>(&result) = *this;
|
||||
|
||||
// Even though we zero out |result| before copying the long double value,
|
||||
// there can be garbage bits in the padding. So, we zero the padding bits
|
||||
// in |result|.
|
||||
static constexpr UIntType mask =
|
||||
(UIntType(1) << (sizeof(long double) * 8 -
|
||||
Padding<sizeof(uintptr_t)>::value)) -
|
||||
1;
|
||||
return result & mask;
|
||||
}
|
||||
|
||||
static FPBits<long double> zero() { return FPBits<long double>(0.0l); }
|
||||
|
||||
static FPBits<long double> negZero() {
|
||||
FPBits<long double> bits(0.0l);
|
||||
bits.sign = 1;
|
||||
bits.encoding.sign = 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
static FPBits<long double> inf() {
|
||||
FPBits<long double> bits(0.0l);
|
||||
bits.exponent = maxExponent;
|
||||
bits.implicitBit = 1;
|
||||
bits.encoding.exponent = maxExponent;
|
||||
bits.encoding.implicitBit = 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
static FPBits<long double> negInf() {
|
||||
FPBits<long double> bits(0.0l);
|
||||
bits.exponent = maxExponent;
|
||||
bits.implicitBit = 1;
|
||||
bits.sign = 1;
|
||||
bits.encoding.exponent = maxExponent;
|
||||
bits.encoding.implicitBit = 1;
|
||||
bits.encoding.sign = 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
static long double buildNaN(UIntType v) {
|
||||
FPBits<long double> bits(0.0l);
|
||||
bits.exponent = maxExponent;
|
||||
bits.implicitBit = 1;
|
||||
bits.mantissa = v;
|
||||
bits.encoding.exponent = maxExponent;
|
||||
bits.encoding.implicitBit = 1;
|
||||
bits.encoding.mantissa = v;
|
||||
return bits;
|
||||
}
|
||||
};
|
||||
|
@ -47,13 +47,13 @@ static inline T modf(T x, T &iptr) {
|
||||
return x;
|
||||
} else if (bits.isInf()) {
|
||||
iptr = x;
|
||||
return bits.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
|
||||
return bits.encoding.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
|
||||
} else {
|
||||
iptr = trunc(x);
|
||||
if (x == iptr) {
|
||||
// If x is already an integer value, then return zero with the right
|
||||
// sign.
|
||||
return bits.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
|
||||
return bits.encoding.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
|
||||
} else {
|
||||
return x - iptr;
|
||||
}
|
||||
@ -64,7 +64,7 @@ template <typename T,
|
||||
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
|
||||
static inline T copysign(T x, T y) {
|
||||
FPBits<T> xbits(x);
|
||||
xbits.sign = FPBits<T>(y).sign;
|
||||
xbits.encoding.sign = FPBits<T>(y).encoding.sign;
|
||||
return xbits;
|
||||
}
|
||||
|
||||
@ -131,11 +131,11 @@ static inline T ldexp(T x, int exp) {
|
||||
// calculating the limit.
|
||||
int expLimit = FPBits<T>::maxExponent + MantissaWidth<T>::value + 1;
|
||||
if (exp > expLimit)
|
||||
return bits.sign ? FPBits<T>::negInf() : FPBits<T>::inf();
|
||||
return bits.encoding.sign ? FPBits<T>::negInf() : FPBits<T>::inf();
|
||||
|
||||
// Similarly on the negative side we return zero early if |exp| is too small.
|
||||
if (exp < -expLimit)
|
||||
return bits.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
|
||||
return bits.encoding.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
|
||||
|
||||
// For all other values, NormalFloat to T conversion handles it the right way.
|
||||
NormalFloat<T> normal(bits);
|
||||
@ -158,7 +158,7 @@ static inline T nextafter(T from, T to) {
|
||||
return to;
|
||||
|
||||
using UIntType = typename FPBits<T>::UIntType;
|
||||
auto intVal = fromBits.bitsAsUInt();
|
||||
UIntType intVal = fromBits.uintval();
|
||||
UIntType signMask = (UIntType(1) << (sizeof(T) * 8 - 1));
|
||||
if (from != T(0.0)) {
|
||||
if ((from < to) == (from > T(0.0))) {
|
||||
@ -167,7 +167,7 @@ static inline T nextafter(T from, T to) {
|
||||
--intVal;
|
||||
}
|
||||
} else {
|
||||
intVal = (toBits.bitsAsUInt() & signMask) + UIntType(1);
|
||||
intVal = (UIntType(toBits) & signMask) + UIntType(1);
|
||||
}
|
||||
|
||||
return *reinterpret_cast<T *>(&intVal);
|
||||
|
@ -43,14 +43,14 @@ static inline T trunc(T x) {
|
||||
|
||||
// If the exponent is such that abs(x) is less than 1, then return 0.
|
||||
if (exponent <= -1) {
|
||||
if (bits.sign)
|
||||
if (bits.encoding.sign)
|
||||
return T(-0.0);
|
||||
else
|
||||
return T(0.0);
|
||||
}
|
||||
|
||||
int trimSize = MantissaWidth<T>::value - exponent;
|
||||
bits.mantissa = (bits.mantissa >> trimSize) << trimSize;
|
||||
bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
|
||||
return bits;
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ static inline T ceil(T x) {
|
||||
if (bits.isInfOrNaN() || bits.isZero())
|
||||
return x;
|
||||
|
||||
bool isNeg = bits.sign;
|
||||
bool isNeg = bits.encoding.sign;
|
||||
int exponent = bits.getExponent();
|
||||
|
||||
// If the exponent is greater than the most negative mantissa
|
||||
@ -79,7 +79,7 @@ static inline T ceil(T x) {
|
||||
}
|
||||
|
||||
uint32_t trimSize = MantissaWidth<T>::value - exponent;
|
||||
bits.mantissa = (bits.mantissa >> trimSize) << trimSize;
|
||||
bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
|
||||
T truncValue = T(bits);
|
||||
|
||||
// If x is already an integer, return it.
|
||||
@ -97,7 +97,7 @@ template <typename T,
|
||||
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
|
||||
static inline T floor(T x) {
|
||||
FPBits<T> bits(x);
|
||||
if (bits.sign) {
|
||||
if (bits.encoding.sign) {
|
||||
return -ceil(-x);
|
||||
} else {
|
||||
return trunc(x);
|
||||
@ -114,7 +114,7 @@ static inline T round(T x) {
|
||||
if (bits.isInfOrNaN() || bits.isZero())
|
||||
return x;
|
||||
|
||||
bool isNeg = bits.sign;
|
||||
bool isNeg = bits.encoding.sign;
|
||||
int exponent = bits.getExponent();
|
||||
|
||||
// If the exponent is greater than the most negative mantissa
|
||||
@ -139,8 +139,8 @@ static inline T round(T x) {
|
||||
}
|
||||
|
||||
uint32_t trimSize = MantissaWidth<T>::value - exponent;
|
||||
bool halfBitSet = bits.mantissa & (UIntType(1) << (trimSize - 1));
|
||||
bits.mantissa = (bits.mantissa >> trimSize) << trimSize;
|
||||
bool halfBitSet = bits.encoding.mantissa & (UIntType(1) << (trimSize - 1));
|
||||
bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
|
||||
T truncValue = T(bits);
|
||||
|
||||
// If x is already an integer, return it.
|
||||
@ -166,7 +166,7 @@ static inline T roundUsingCurrentRoundingMode(T x) {
|
||||
if (bits.isInfOrNaN() || bits.isZero())
|
||||
return x;
|
||||
|
||||
bool isNeg = bits.sign;
|
||||
bool isNeg = bits.encoding.sign;
|
||||
int exponent = bits.getExponent();
|
||||
int roundingMode = getRound();
|
||||
|
||||
@ -184,7 +184,7 @@ static inline T roundUsingCurrentRoundingMode(T x) {
|
||||
case FE_TOWARDZERO:
|
||||
return isNeg ? T(-0.0) : T(0.0);
|
||||
case FE_TONEAREST:
|
||||
if (exponent <= -2 || bits.mantissa == 0)
|
||||
if (exponent <= -2 || bits.encoding.mantissa == 0)
|
||||
return isNeg ? T(-0.0) : T(0.0); // abs(x) <= 0.5
|
||||
else
|
||||
return isNeg ? T(-1.0) : T(1.0); // abs(x) > 0.5
|
||||
@ -195,19 +195,19 @@ static inline T roundUsingCurrentRoundingMode(T x) {
|
||||
|
||||
uint32_t trimSize = MantissaWidth<T>::value - exponent;
|
||||
FPBits<T> newBits = bits;
|
||||
newBits.mantissa = (bits.mantissa >> trimSize) << trimSize;
|
||||
newBits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
|
||||
T truncValue = T(newBits);
|
||||
|
||||
// If x is already an integer, return it.
|
||||
if (truncValue == x)
|
||||
return x;
|
||||
|
||||
UIntType trimValue = bits.mantissa & ((UIntType(1) << trimSize) - 1);
|
||||
UIntType trimValue = bits.encoding.mantissa & ((UIntType(1) << trimSize) - 1);
|
||||
UIntType halfValue = (UIntType(1) << (trimSize - 1));
|
||||
// If exponent is 0, trimSize will be equal to the mantissa width, and
|
||||
// truncIsOdd` will not be correct. So, we handle it as a special case
|
||||
// below.
|
||||
UIntType truncIsOdd = newBits.mantissa & (UIntType(1) << trimSize);
|
||||
UIntType truncIsOdd = newBits.encoding.mantissa & (UIntType(1) << trimSize);
|
||||
|
||||
switch (roundingMode) {
|
||||
case FE_DOWNWARD:
|
||||
@ -255,18 +255,18 @@ static inline I roundedFloatToSignedInteger(F x) {
|
||||
|
||||
if (bits.isInfOrNaN()) {
|
||||
setDomainErrorAndRaiseInvalid();
|
||||
return bits.sign ? IntegerMin : IntegerMax;
|
||||
return bits.encoding.sign ? IntegerMin : IntegerMax;
|
||||
}
|
||||
|
||||
int exponent = bits.getExponent();
|
||||
constexpr int exponentLimit = sizeof(I) * 8 - 1;
|
||||
if (exponent > exponentLimit) {
|
||||
setDomainErrorAndRaiseInvalid();
|
||||
return bits.sign ? IntegerMin : IntegerMax;
|
||||
return bits.encoding.sign ? IntegerMin : IntegerMax;
|
||||
} else if (exponent == exponentLimit) {
|
||||
if (bits.sign == 0 || bits.mantissa != 0) {
|
||||
if (bits.encoding.sign == 0 || bits.encoding.mantissa != 0) {
|
||||
setDomainErrorAndRaiseInvalid();
|
||||
return bits.sign ? IntegerMin : IntegerMax;
|
||||
return bits.encoding.sign ? IntegerMin : IntegerMax;
|
||||
}
|
||||
// If the control reaches here, then it means that the rounded
|
||||
// value is the most negative number for the signed integer type I.
|
||||
|
@ -30,15 +30,15 @@ static inline long double nextafter(long double from, long double to) {
|
||||
return to;
|
||||
|
||||
// Convert pseudo subnormal number to normal number.
|
||||
if (fromBits.implicitBit == 1 && fromBits.exponent == 0) {
|
||||
fromBits.exponent = 1;
|
||||
if (fromBits.encoding.implicitBit == 1 && fromBits.encoding.exponent == 0) {
|
||||
fromBits.encoding.exponent = 1;
|
||||
}
|
||||
|
||||
using UIntType = FPBits::UIntType;
|
||||
constexpr UIntType signVal = (UIntType(1) << 79);
|
||||
constexpr UIntType mantissaMask =
|
||||
(UIntType(1) << MantissaWidth<long double>::value) - 1;
|
||||
auto intVal = fromBits.bitsAsUInt();
|
||||
UIntType intVal = fromBits.uintval();
|
||||
if (from < 0.0l) {
|
||||
if (from > to) {
|
||||
if (intVal == (signVal + FPBits::maxSubnormal)) {
|
||||
@ -46,11 +46,11 @@ static inline long double nextafter(long double from, long double to) {
|
||||
// dealing with the implicit bit.
|
||||
intVal = signVal + FPBits::minNormal;
|
||||
} else if ((intVal & mantissaMask) == mantissaMask) {
|
||||
fromBits.mantissa = 0;
|
||||
fromBits.encoding.mantissa = 0;
|
||||
// Incrementing exponent might overflow the value to infinity,
|
||||
// which is what is expected. Since NaNs are handling separately,
|
||||
// it will never overflow "beyond" infinity.
|
||||
++fromBits.exponent;
|
||||
++fromBits.encoding.exponent;
|
||||
return fromBits;
|
||||
} else {
|
||||
++intVal;
|
||||
@ -61,10 +61,10 @@ static inline long double nextafter(long double from, long double to) {
|
||||
// dealing with the implicit bit.
|
||||
intVal = signVal + FPBits::maxSubnormal;
|
||||
} else if ((intVal & mantissaMask) == 0) {
|
||||
fromBits.mantissa = mantissaMask;
|
||||
fromBits.encoding.mantissa = mantissaMask;
|
||||
// from == 0 is handled separately so decrementing the exponent will not
|
||||
// lead to underflow.
|
||||
--fromBits.exponent;
|
||||
--fromBits.encoding.exponent;
|
||||
return fromBits;
|
||||
} else {
|
||||
--intVal;
|
||||
@ -80,10 +80,10 @@ static inline long double nextafter(long double from, long double to) {
|
||||
if (intVal == FPBits::minNormal) {
|
||||
intVal = FPBits::maxSubnormal;
|
||||
} else if ((intVal & mantissaMask) == 0) {
|
||||
fromBits.mantissa = mantissaMask;
|
||||
fromBits.encoding.mantissa = mantissaMask;
|
||||
// from == 0 is handled separately so decrementing the exponent will not
|
||||
// lead to underflow.
|
||||
--fromBits.exponent;
|
||||
--fromBits.encoding.exponent;
|
||||
return fromBits;
|
||||
} else {
|
||||
--intVal;
|
||||
@ -92,11 +92,11 @@ static inline long double nextafter(long double from, long double to) {
|
||||
if (intVal == FPBits::maxSubnormal) {
|
||||
intVal = FPBits::minNormal;
|
||||
} else if ((intVal & mantissaMask) == mantissaMask) {
|
||||
fromBits.mantissa = 0;
|
||||
fromBits.encoding.mantissa = 0;
|
||||
// Incrementing exponent might overflow the value to infinity,
|
||||
// which is what is expected. Since NaNs are handling separately,
|
||||
// it will never overflow "beyond" infinity.
|
||||
++fromBits.exponent;
|
||||
++fromBits.encoding.exponent;
|
||||
return fromBits;
|
||||
} else {
|
||||
++intVal;
|
||||
|
@ -97,7 +97,7 @@ template <typename T> struct NormalFloat {
|
||||
}
|
||||
|
||||
FPBits<T> result(T(0.0));
|
||||
result.sign = sign;
|
||||
result.encoding.sign = sign;
|
||||
|
||||
constexpr int subnormalExponent = -FPBits<T>::exponentBias + 1;
|
||||
if (exponent < subnormalExponent) {
|
||||
@ -110,36 +110,36 @@ template <typename T> struct NormalFloat {
|
||||
const UIntType shiftOutMask = (UIntType(1) << shift) - 1;
|
||||
const UIntType shiftOutValue = mantissa & shiftOutMask;
|
||||
const UIntType halfwayValue = UIntType(1) << (shift - 1);
|
||||
result.exponent = 0;
|
||||
result.mantissa = mantissa >> shift;
|
||||
UIntType newMantissa = result.mantissa;
|
||||
result.encoding.exponent = 0;
|
||||
result.encoding.mantissa = mantissa >> shift;
|
||||
UIntType newMantissa = result.encoding.mantissa;
|
||||
if (shiftOutValue > halfwayValue) {
|
||||
newMantissa += 1;
|
||||
} else if (shiftOutValue == halfwayValue) {
|
||||
// Round to even.
|
||||
if (result.mantissa & 0x1)
|
||||
if (result.encoding.mantissa & 0x1)
|
||||
newMantissa += 1;
|
||||
}
|
||||
result.mantissa = newMantissa;
|
||||
result.encoding.mantissa = newMantissa;
|
||||
// Adding 1 to mantissa can lead to overflow. This can only happen if
|
||||
// mantissa was all ones (0b111..11). For such a case, we will carry
|
||||
// the overflow into the exponent.
|
||||
if (newMantissa == one)
|
||||
result.exponent = 1;
|
||||
result.encoding.exponent = 1;
|
||||
return result;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.exponent = exponent + FPBits<T>::exponentBias;
|
||||
result.mantissa = mantissa;
|
||||
result.encoding.exponent = exponent + FPBits<T>::exponentBias;
|
||||
result.encoding.mantissa = mantissa;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void initFromBits(FPBits<T> bits) {
|
||||
sign = bits.sign;
|
||||
sign = bits.encoding.sign;
|
||||
|
||||
if (bits.isInfOrNaN() || bits.isZero()) {
|
||||
// Ignore special bit patterns. Implementations deal with them separately
|
||||
@ -150,13 +150,13 @@ private:
|
||||
}
|
||||
|
||||
// Normalize subnormal numbers.
|
||||
if (bits.exponent == 0) {
|
||||
unsigned shift = evaluateNormalizationShift(bits.mantissa);
|
||||
mantissa = UIntType(bits.mantissa) << shift;
|
||||
if (bits.encoding.exponent == 0) {
|
||||
unsigned shift = evaluateNormalizationShift(bits.encoding.mantissa);
|
||||
mantissa = UIntType(bits.encoding.mantissa) << shift;
|
||||
exponent = 1 - FPBits<T>::exponentBias - shift;
|
||||
} else {
|
||||
exponent = bits.exponent - FPBits<T>::exponentBias;
|
||||
mantissa = one | bits.mantissa;
|
||||
exponent = bits.encoding.exponent - FPBits<T>::exponentBias;
|
||||
mantissa = one | bits.encoding.mantissa;
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ private:
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
template <>
|
||||
inline void NormalFloat<long double>::initFromBits(FPBits<long double> bits) {
|
||||
sign = bits.sign;
|
||||
sign = bits.encoding.sign;
|
||||
|
||||
if (bits.isInfOrNaN() || bits.isZero()) {
|
||||
// Ignore special bit patterns. Implementations deal with them separately
|
||||
@ -182,24 +182,25 @@ inline void NormalFloat<long double>::initFromBits(FPBits<long double> bits) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bits.exponent == 0) {
|
||||
if (bits.implicitBit == 0) {
|
||||
if (bits.encoding.exponent == 0) {
|
||||
if (bits.encoding.implicitBit == 0) {
|
||||
// Since we ignore zero value, the mantissa in this case is non-zero.
|
||||
int normalizationShift = evaluateNormalizationShift(bits.mantissa);
|
||||
int normalizationShift =
|
||||
evaluateNormalizationShift(bits.encoding.mantissa);
|
||||
exponent = -16382 - normalizationShift;
|
||||
mantissa = (bits.mantissa << normalizationShift);
|
||||
mantissa = (bits.encoding.mantissa << normalizationShift);
|
||||
} else {
|
||||
exponent = -16382;
|
||||
mantissa = one | bits.mantissa;
|
||||
mantissa = one | bits.encoding.mantissa;
|
||||
}
|
||||
} else {
|
||||
if (bits.implicitBit == 0) {
|
||||
if (bits.encoding.implicitBit == 0) {
|
||||
// Invalid number so just store 0 similar to a NaN.
|
||||
exponent = 0;
|
||||
mantissa = 0;
|
||||
} else {
|
||||
exponent = bits.exponent - 16383;
|
||||
mantissa = one | bits.mantissa;
|
||||
exponent = bits.encoding.exponent - 16383;
|
||||
mantissa = one | bits.encoding.mantissa;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,7 +214,7 @@ template <> inline NormalFloat<long double>::operator long double() const {
|
||||
}
|
||||
|
||||
FPBits<long double> result(0.0l);
|
||||
result.sign = sign;
|
||||
result.encoding.sign = sign;
|
||||
|
||||
constexpr int subnormalExponent = -FPBits<long double>::exponentBias + 1;
|
||||
if (exponent < subnormalExponent) {
|
||||
@ -224,25 +225,25 @@ template <> inline NormalFloat<long double>::operator long double() const {
|
||||
const UIntType shiftOutMask = (UIntType(1) << shift) - 1;
|
||||
const UIntType shiftOutValue = mantissa & shiftOutMask;
|
||||
const UIntType halfwayValue = UIntType(1) << (shift - 1);
|
||||
result.exponent = 0;
|
||||
result.mantissa = mantissa >> shift;
|
||||
UIntType newMantissa = result.mantissa;
|
||||
result.encoding.exponent = 0;
|
||||
result.encoding.mantissa = mantissa >> shift;
|
||||
UIntType newMantissa = result.encoding.mantissa;
|
||||
if (shiftOutValue > halfwayValue) {
|
||||
newMantissa += 1;
|
||||
} else if (shiftOutValue == halfwayValue) {
|
||||
// Round to even.
|
||||
if (result.mantissa & 0x1)
|
||||
if (result.encoding.mantissa & 0x1)
|
||||
newMantissa += 1;
|
||||
}
|
||||
result.mantissa = newMantissa;
|
||||
result.encoding.mantissa = newMantissa;
|
||||
// Adding 1 to mantissa can lead to overflow. This can only happen if
|
||||
// mantissa was all ones (0b111..11). For such a case, we will carry
|
||||
// the overflow into the exponent and set the implicit bit to 1.
|
||||
if (newMantissa == one) {
|
||||
result.exponent = 1;
|
||||
result.implicitBit = 1;
|
||||
result.encoding.exponent = 1;
|
||||
result.encoding.implicitBit = 1;
|
||||
} else {
|
||||
result.implicitBit = 0;
|
||||
result.encoding.implicitBit = 0;
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
@ -250,9 +251,9 @@ template <> inline NormalFloat<long double>::operator long double() const {
|
||||
}
|
||||
}
|
||||
|
||||
result.exponent = biasedExponent;
|
||||
result.mantissa = mantissa;
|
||||
result.implicitBit = 1;
|
||||
result.encoding.exponent = biasedExponent;
|
||||
result.encoding.mantissa = mantissa;
|
||||
result.encoding.implicitBit = 1;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
@ -96,7 +96,7 @@ static inline T sqrt(T x) {
|
||||
FPBits<T> bits(x);
|
||||
|
||||
if (bits.isInfOrNaN()) {
|
||||
if (bits.sign && (bits.mantissa == 0)) {
|
||||
if (bits.encoding.sign && (bits.encoding.mantissa == 0)) {
|
||||
// sqrt(-Inf) = NaN
|
||||
return FPBits<T>::buildNaN(One >> 1);
|
||||
} else {
|
||||
@ -108,15 +108,15 @@ static inline T sqrt(T x) {
|
||||
// sqrt(+0) = +0
|
||||
// sqrt(-0) = -0
|
||||
return x;
|
||||
} else if (bits.sign) {
|
||||
} else if (bits.encoding.sign) {
|
||||
// sqrt( negative numbers ) = NaN
|
||||
return FPBits<T>::buildNaN(One >> 1);
|
||||
} else {
|
||||
int xExp = bits.getExponent();
|
||||
UIntType xMant = bits.mantissa;
|
||||
UIntType xMant = bits.encoding.mantissa;
|
||||
|
||||
// Step 1a: Normalize denormal input and append hiddent bit to the mantissa
|
||||
if (bits.exponent == 0) {
|
||||
if (bits.encoding.exponent == 0) {
|
||||
++xExp; // let xExp be the correct exponent of One bit.
|
||||
internal::normalize<T>(xExp, xMant);
|
||||
} else {
|
||||
|
@ -51,7 +51,7 @@ template <> inline long double sqrt<long double, 0>(long double x) {
|
||||
FPBits<long double> bits(x);
|
||||
|
||||
if (bits.isInfOrNaN()) {
|
||||
if (bits.sign && (bits.mantissa == 0)) {
|
||||
if (bits.encoding.sign && (bits.encoding.mantissa == 0)) {
|
||||
// sqrt(-Inf) = NaN
|
||||
return FPBits<long double>::buildNaN(One >> 1);
|
||||
} else {
|
||||
@ -63,17 +63,17 @@ template <> inline long double sqrt<long double, 0>(long double x) {
|
||||
// sqrt(+0) = +0
|
||||
// sqrt(-0) = -0
|
||||
return x;
|
||||
} else if (bits.sign) {
|
||||
} else if (bits.encoding.sign) {
|
||||
// sqrt( negative numbers ) = NaN
|
||||
return FPBits<long double>::buildNaN(One >> 1);
|
||||
} else {
|
||||
int xExp = bits.getExponent();
|
||||
UIntType xMant = bits.mantissa;
|
||||
UIntType xMant = bits.encoding.mantissa;
|
||||
|
||||
// Step 1a: Normalize denormal input
|
||||
if (bits.implicitBit) {
|
||||
if (bits.encoding.implicitBit) {
|
||||
xMant |= One;
|
||||
} else if (bits.exponent == 0) {
|
||||
} else if (bits.encoding.exponent == 0) {
|
||||
internal::normalize<long double>(xExp, xMant);
|
||||
}
|
||||
|
||||
@ -129,9 +129,9 @@ template <> inline long double sqrt<long double, 0>(long double x) {
|
||||
|
||||
// Extract output
|
||||
FPBits<long double> out(0.0L);
|
||||
out.exponent = xExp;
|
||||
out.implicitBit = 1;
|
||||
out.mantissa = (y & (One - 1));
|
||||
out.encoding.exponent = xExp;
|
||||
out.encoding.implicitBit = 1;
|
||||
out.encoding.mantissa = (y & (One - 1));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ describeValue(const char *label, ValType value,
|
||||
if (bits.isNaN()) {
|
||||
stream << "(NaN)";
|
||||
} else if (bits.isInf()) {
|
||||
if (bits.sign)
|
||||
if (bits.encoding.sign)
|
||||
stream << "(-Infinity)";
|
||||
else
|
||||
stream << "(+Infinity)";
|
||||
@ -50,12 +50,13 @@ describeValue(const char *label, ValType value,
|
||||
constexpr int mantissaWidthInHex =
|
||||
(fputil::MantissaWidth<ValType>::value - 1) / 4 + 1;
|
||||
|
||||
stream << "Sign: " << (bits.sign ? '1' : '0') << ", "
|
||||
stream << "Sign: " << (bits.encoding.sign ? '1' : '0') << ", "
|
||||
<< "Exponent: 0x"
|
||||
<< uintToHex<uint16_t>(bits.exponent, exponentWidthInHex) << ", "
|
||||
<< uintToHex<uint16_t>(bits.encoding.exponent, exponentWidthInHex)
|
||||
<< ", "
|
||||
<< "Mantissa: 0x"
|
||||
<< uintToHex<typename fputil::FPBits<ValType>::UIntType>(
|
||||
bits.mantissa, mantissaWidthInHex);
|
||||
bits.encoding.mantissa, mantissaWidthInHex);
|
||||
}
|
||||
|
||||
stream << '\n';
|
||||
|
@ -41,13 +41,13 @@ public:
|
||||
fputil::FPBits<T> actualBits(actual), expectedBits(expected);
|
||||
if (Condition == __llvm_libc::testing::Cond_EQ)
|
||||
return (actualBits.isNaN() && expectedBits.isNaN()) ||
|
||||
(actualBits.bitsAsUInt() == expectedBits.bitsAsUInt());
|
||||
(actualBits.uintval() == expectedBits.uintval());
|
||||
|
||||
// If condition == Cond_NE.
|
||||
if (actualBits.isNaN())
|
||||
return !expectedBits.isNaN();
|
||||
return expectedBits.isNaN() ||
|
||||
(actualBits.bitsAsUInt() != expectedBits.bitsAsUInt());
|
||||
(actualBits.uintval() != expectedBits.uintval());
|
||||
}
|
||||
|
||||
void explainError(testutils::StreamWrapper &stream) override {
|
||||
|
@ -264,12 +264,12 @@ public:
|
||||
mpfr_abs(mpfrInput.value, mpfrInput.value, MPFR_RNDN);
|
||||
|
||||
// get eps(input)
|
||||
int epsExponent = bits.exponent - fputil::FPBits<T>::exponentBias -
|
||||
int epsExponent = bits.encoding.exponent - fputil::FPBits<T>::exponentBias -
|
||||
fputil::MantissaWidth<T>::value;
|
||||
if (bits.exponent == 0) {
|
||||
if (bits.encoding.exponent == 0) {
|
||||
// correcting denormal exponent
|
||||
++epsExponent;
|
||||
} else if ((bits.mantissa == 0) && (bits.exponent > 1) &&
|
||||
} else if ((bits.encoding.mantissa == 0) && (bits.encoding.exponent > 1) &&
|
||||
mpfr_less_p(value, mpfrInput.value)) {
|
||||
// when the input is exactly 2^n, distance (epsilon) between the input
|
||||
// and the next floating point number is different from the distance to
|
||||
@ -567,7 +567,7 @@ bool compareUnaryOperationSingleOutput(Operation op, T input, T libcResult,
|
||||
// is rounded to the nearest even.
|
||||
MPFRNumber mpfrResult = unaryOperation(op, input);
|
||||
double ulp = mpfrResult.ulp(libcResult);
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult).bitsAsUInt() & 1) == 0);
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult).uintval() & 1) == 0);
|
||||
return (ulp < ulpError) ||
|
||||
((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
|
||||
}
|
||||
@ -592,7 +592,7 @@ bool compareUnaryOperationTwoOutputs(Operation op, T input,
|
||||
if (mpfrIntResult != libcResult.i)
|
||||
return false;
|
||||
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult.f).bitsAsUInt() & 1) == 0);
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult.f).uintval() & 1) == 0);
|
||||
return (ulp < ulpError) ||
|
||||
((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
|
||||
}
|
||||
@ -624,7 +624,7 @@ bool compareBinaryOperationTwoOutputs(Operation op, const BinaryInput<T> &input,
|
||||
}
|
||||
}
|
||||
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult.f).bitsAsUInt() & 1) == 0);
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult.f).uintval() & 1) == 0);
|
||||
return (ulp < ulpError) ||
|
||||
((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
|
||||
}
|
||||
@ -645,7 +645,7 @@ bool compareBinaryOperationOneOutput(Operation op, const BinaryInput<T> &input,
|
||||
MPFRNumber mpfrResult = binaryOperationOneOutput(op, input.x, input.y);
|
||||
double ulp = mpfrResult.ulp(libcResult);
|
||||
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult).bitsAsUInt() & 1) == 0);
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult).uintval() & 1) == 0);
|
||||
return (ulp < ulpError) ||
|
||||
((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
|
||||
}
|
||||
@ -667,7 +667,7 @@ bool compareTernaryOperationOneOutput(Operation op,
|
||||
ternaryOperationOneOutput(op, input.x, input.y, input.z);
|
||||
double ulp = mpfrResult.ulp(libcResult);
|
||||
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult).bitsAsUInt() & 1) == 0);
|
||||
bool bitsAreEven = ((FPBits<T>(libcResult).uintval() & 1) == 0);
|
||||
return (ulp < ulpError) ||
|
||||
((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user