1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

APFloat: Add frexp

llvm-svn: 263950
This commit is contained in:
Matt Arsenault 2016-03-21 16:49:16 +00:00
parent 25e104f5af
commit 5d7eb096ca
3 changed files with 161 additions and 2 deletions

View File

@ -516,6 +516,8 @@ public:
/// \brief Returns: X * 2^Exp for integral exponents.
friend APFloat scalbn(APFloat X, int Exp, roundingMode);
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode);
private:
/// \name Simple Queries
@ -570,6 +572,7 @@ private:
const APInt *fill);
void makeInf(bool Neg = false);
void makeZero(bool Neg = false);
void makeQuiet();
/// @}
@ -645,6 +648,12 @@ hash_code hash_value(const APFloat &Arg);
int ilogb(const APFloat &Arg);
APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode);
/// \brief Equivalent of C standard library function.
///
/// While the C standard says Exp is an unspecified value for infinity and nan,
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
APFloat frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM);
/// \brief Returns the absolute value of the argument.
inline APFloat abs(APFloat X) {
X.clearSign();

View File

@ -3945,6 +3945,11 @@ APFloat::makeZero(bool Negative) {
APInt::tcSet(significandParts(), 0, partCount());
}
void APFloat::makeQuiet() {
assert(isNaN());
APInt::tcSetBit(significandParts(), semantics->precision - 2);
}
int llvm::ilogb(const APFloat &Arg) {
if (Arg.isNaN())
return APFloat::IEK_NaN;
@ -3981,3 +3986,22 @@ APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) {
X.normalize(RoundingMode, lfExactlyZero);
return X;
}
APFloat llvm::frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM) {
Exp = ilogb(Val);
// Quiet signalling nans.
if (Exp == APFloat::IEK_NaN) {
APFloat Quiet(Val);
Quiet.makeQuiet();
return Quiet;
}
if (Exp == APFloat::IEK_Inf)
return Val;
// 1 is added because frexp is defined to return a normalized fraction in
// +/-[0.5, 1.0), rather than the usual +/-[1.0, 2.0).
Exp = Exp == APFloat::IEK_Zero ? 0 : Exp + 1;
return scalbn(Val, -Exp, RM);
}

View File

@ -3018,4 +3018,130 @@ TEST(APFloatTest, scalbn) {
APFloat(APFloat::IEEEdouble, "0x1p-103")
.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble, "0x1p-51"), -52, RM)));
}
TEST(APFloatTest, frexp) {
const APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
APFloat PZero = APFloat::getZero(APFloat::IEEEdouble, false);
APFloat MZero = APFloat::getZero(APFloat::IEEEdouble, true);
APFloat One(1.0);
APFloat MOne(-1.0);
APFloat Two(2.0);
APFloat MTwo(-2.0);
APFloat LargestDenormal(APFloat::IEEEdouble, "0x1.ffffffffffffep-1023");
APFloat NegLargestDenormal(APFloat::IEEEdouble, "-0x1.ffffffffffffep-1023");
APFloat Smallest = APFloat::getSmallest(APFloat::IEEEdouble, false);
APFloat NegSmallest = APFloat::getSmallest(APFloat::IEEEdouble, true);
APFloat Largest = APFloat::getLargest(APFloat::IEEEdouble, false);
APFloat NegLargest = APFloat::getLargest(APFloat::IEEEdouble, true);
APFloat PInf = APFloat::getInf(APFloat::IEEEdouble, false);
APFloat MInf = APFloat::getInf(APFloat::IEEEdouble, true);
APFloat QPNaN = APFloat::getNaN(APFloat::IEEEdouble, false);
APFloat QMNaN = APFloat::getNaN(APFloat::IEEEdouble, true);
APFloat SNaN = APFloat::getSNaN(APFloat::IEEEdouble, false);
// Make sure highest bit of payload is preserved.
const APInt Payload(64, (UINT64_C(1) << 50) |
(UINT64_C(1) << 49) |
(UINT64_C(1234) << 32) |
1);
APFloat SNaNWithPayload = APFloat::getSNaN(APFloat::IEEEdouble, false,
&Payload);
APFloat SmallestNormalized
= APFloat::getSmallestNormalized(APFloat::IEEEdouble, false);
APFloat NegSmallestNormalized
= APFloat::getSmallestNormalized(APFloat::IEEEdouble, true);
int Exp;
APFloat Frac(APFloat::IEEEdouble);
Frac = frexp(PZero, Exp, RM);
EXPECT_EQ(0, Exp);
EXPECT_TRUE(Frac.isPosZero());
Frac = frexp(MZero, Exp, RM);
EXPECT_EQ(0, Exp);
EXPECT_TRUE(Frac.isNegZero());
Frac = frexp(One, Exp, RM);
EXPECT_EQ(1, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1p-1").bitwiseIsEqual(Frac));
Frac = frexp(MOne, Exp, RM);
EXPECT_EQ(1, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-0x1p-1").bitwiseIsEqual(Frac));
Frac = frexp(LargestDenormal, Exp, RM);
EXPECT_EQ(-1022, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-1").bitwiseIsEqual(Frac));
Frac = frexp(NegLargestDenormal, Exp, RM);
EXPECT_EQ(-1022, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-0x1.ffffffffffffep-1").bitwiseIsEqual(Frac));
Frac = frexp(Smallest, Exp, RM);
EXPECT_EQ(-1073, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1p-1").bitwiseIsEqual(Frac));
Frac = frexp(NegSmallest, Exp, RM);
EXPECT_EQ(-1073, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-0x1p-1").bitwiseIsEqual(Frac));
Frac = frexp(Largest, Exp, RM);
EXPECT_EQ(1024, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.fffffffffffffp-1").bitwiseIsEqual(Frac));
Frac = frexp(NegLargest, Exp, RM);
EXPECT_EQ(1024, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-0x1.fffffffffffffp-1").bitwiseIsEqual(Frac));
Frac = frexp(PInf, Exp, RM);
EXPECT_EQ(INT_MAX, Exp);
EXPECT_TRUE(Frac.isInfinity() && !Frac.isNegative());
Frac = frexp(MInf, Exp, RM);
EXPECT_EQ(INT_MAX, Exp);
EXPECT_TRUE(Frac.isInfinity() && Frac.isNegative());
Frac = frexp(QPNaN, Exp, RM);
EXPECT_EQ(INT_MIN, Exp);
EXPECT_TRUE(Frac.isNaN());
Frac = frexp(QMNaN, Exp, RM);
EXPECT_EQ(INT_MIN, Exp);
EXPECT_TRUE(Frac.isNaN());
Frac = frexp(SNaN, Exp, RM);
EXPECT_EQ(INT_MIN, Exp);
EXPECT_TRUE(Frac.isNaN() && !Frac.isSignaling());
Frac = frexp(SNaNWithPayload, Exp, RM);
EXPECT_EQ(INT_MIN, Exp);
EXPECT_TRUE(Frac.isNaN() && !Frac.isSignaling());
EXPECT_EQ(Payload, Frac.bitcastToAPInt().getLoBits(51));
Frac = frexp(APFloat(APFloat::IEEEdouble, "0x0.ffffp-1"), Exp, RM);
EXPECT_EQ(-1, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.fffep-1").bitwiseIsEqual(Frac));
Frac = frexp(APFloat(APFloat::IEEEdouble, "0x1p-51"), Exp, RM);
EXPECT_EQ(-50, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1p-1").bitwiseIsEqual(Frac));
Frac = frexp(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp+51"), Exp, RM);
EXPECT_EQ(52, Exp);
EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp-1").bitwiseIsEqual(Frac));
}
}