[llvm] r263950 - APFloat: Add frexp
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 21 09:49:17 PDT 2016
Author: arsenm
Date: Mon Mar 21 11:49:16 2016
New Revision: 263950
URL: http://llvm.org/viewvc/llvm-project?rev=263950&view=rev
Log:
APFloat: Add frexp
Modified:
llvm/trunk/include/llvm/ADT/APFloat.h
llvm/trunk/lib/Support/APFloat.cpp
llvm/trunk/unittests/ADT/APFloatTest.cpp
Modified: llvm/trunk/include/llvm/ADT/APFloat.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APFloat.h?rev=263950&r1=263949&r2=263950&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APFloat.h (original)
+++ llvm/trunk/include/llvm/ADT/APFloat.h Mon Mar 21 11:49:16 2016
@@ -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();
Modified: llvm/trunk/lib/Support/APFloat.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=263950&r1=263949&r2=263950&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Mon Mar 21 11:49:16 2016
@@ -3942,7 +3942,12 @@ APFloat::makeZero(bool Negative) {
category = fcZero;
sign = Negative;
exponent = semantics->minExponent-1;
- APInt::tcSet(significandParts(), 0, partCount());
+ APInt::tcSet(significandParts(), 0, partCount());
+}
+
+void APFloat::makeQuiet() {
+ assert(isNaN());
+ APInt::tcSetBit(significandParts(), semantics->precision - 2);
}
int llvm::ilogb(const APFloat &Arg) {
@@ -3981,3 +3986,22 @@ APFloat llvm::scalbn(APFloat X, int Exp,
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);
+}
Modified: llvm/trunk/unittests/ADT/APFloatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APFloatTest.cpp?rev=263950&r1=263949&r2=263950&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APFloatTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APFloatTest.cpp Mon Mar 21 11:49:16 2016
@@ -1314,7 +1314,7 @@ TEST(APFloatTest, roundToIntegral) {
P.roundToIntegral(APFloat::rmTowardZero);
EXPECT_TRUE(std::isinf(P.convertToDouble()) && P.convertToDouble() < 0.0);
}
-
+
TEST(APFloatTest, isInteger) {
APFloat T(-0.0);
EXPECT_TRUE(T.isInteger());
@@ -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));
+}
}
More information about the llvm-commits
mailing list