From cb84b21243b126db4eb282e6d94c9ccd1d2c2730 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Fri, 10 Oct 2014 04:54:30 +0000 Subject: [PATCH] [ADT] Add the scalbn function for APFloat. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219473 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APFloat.h | 8 +++++-- lib/Support/APFloat.cpp | 17 ++++++++++++++ unittests/ADT/APFloatTest.cpp | 43 +++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 9e8642bfaed..79008494c26 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -507,6 +507,9 @@ public: return Result; } + /// \brief Returns: X * 2^Exp for integral exponents. + friend APFloat scalbn(APFloat X, int Exp); + private: /// \name Simple Queries @@ -628,11 +631,12 @@ private: unsigned int sign : 1; }; -/// See friend declaration above. +/// See friend declarations above. /// -/// This additional declaration is required in order to compile LLVM with IBM +/// These additional declarations are required in order to compile LLVM with IBM /// xlC compiler. hash_code hash_value(const APFloat &Arg); +APFloat scalbn(APFloat X, int Exp); } // namespace llvm diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 659914a85f5..3063a07f9ff 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -3906,3 +3906,20 @@ APFloat::makeZero(bool Negative) { exponent = semantics->minExponent-1; APInt::tcSet(significandParts(), 0, partCount()); } + +APFloat llvm::scalbn(APFloat X, int Exp) { + if (X.isInfinity() || X.isZero() || X.isNaN()) + return std::move(X); + + auto MaxExp = X.getSemantics().maxExponent; + auto MinExp = X.getSemantics().minExponent; + if (Exp > (MaxExp - X.exponent)) + // Overflow saturates to infinity. + return APFloat::getInf(X.getSemantics(), X.isNegative()); + if (Exp < (MinExp - X.exponent)) + // Underflow saturates to zero. + return APFloat::getZero(X.getSemantics(), X.isNegative()); + + X.exponent += Exp; + return std::move(X); +} diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 8dd6f9f9931..bc11dab663f 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -2742,4 +2742,47 @@ TEST(APFloatTest, logb) { EXPECT_TRUE(APFloat(APFloat::IEEEsingle, "-0x7Ep+0") .bitwiseIsEqual(logb(MSmallestNormalized))); } + +TEST(APFloatTest, scalbn) { + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p+0") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 0))); + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p+42") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 42))); + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p-42") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -42))); + + APFloat PInf = APFloat::getInf(APFloat::IEEEsingle, false); + APFloat MInf = APFloat::getInf(APFloat::IEEEsingle, true); + APFloat PZero = APFloat::getZero(APFloat::IEEEsingle, false); + APFloat MZero = APFloat::getZero(APFloat::IEEEsingle, true); + APFloat QPNaN = APFloat::getNaN(APFloat::IEEEsingle, false); + APFloat QMNaN = APFloat::getNaN(APFloat::IEEEsingle, true); + APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle, false); + + EXPECT_TRUE(PInf.bitwiseIsEqual(scalbn(PInf, 0))); + EXPECT_TRUE(MInf.bitwiseIsEqual(scalbn(MInf, 0))); + EXPECT_TRUE(PZero.bitwiseIsEqual(scalbn(PZero, 0))); + EXPECT_TRUE(MZero.bitwiseIsEqual(scalbn(MZero, 0))); + EXPECT_TRUE(QPNaN.bitwiseIsEqual(scalbn(QPNaN, 0))); + EXPECT_TRUE(QMNaN.bitwiseIsEqual(scalbn(QMNaN, 0))); + EXPECT_TRUE(SNaN.bitwiseIsEqual(scalbn(SNaN, 0))); + + EXPECT_TRUE( + PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 128))); + EXPECT_TRUE(MInf.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), 128))); + EXPECT_TRUE( + PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+127"), 1))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -127))); + EXPECT_TRUE(MZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), -127))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); +} } -- 2.34.1