[ADT] Add the scalbn function for APFloat.
authorChandler Carruth <chandlerc@gmail.com>
Fri, 10 Oct 2014 04:54:30 +0000 (04:54 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Fri, 10 Oct 2014 04:54:30 +0000 (04:54 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219473 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/APFloat.h
lib/Support/APFloat.cpp
unittests/ADT/APFloatTest.cpp

index 9e8642bfaed5efd7007f6f97fb1b39c6acc0a92d..79008494c26f1ebd492e3ac6f0c64f35b7eb2ee4 100644 (file)
@@ -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
 
index 659914a85f568a349f2328b2a1930952c572d59f..3063a07f9ff366ad8f898c6df1386505d291042d 100644 (file)
@@ -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);
+}
index 8dd6f9f9931200aa5c51ee2a948b61e54d82ac65..bc11dab663fdf8ba0164cc8c8079d8269884d4ec 100644 (file)
@@ -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)));
+}
 }