[ADT] Replace the logb implementation with the simpler and much closer
authorChandler Carruth <chandlerc@gmail.com>
Fri, 10 Oct 2014 05:14:12 +0000 (05:14 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Fri, 10 Oct 2014 05:14:12 +0000 (05:14 +0000)
to what we actually want ilogb implementation. This makes everything
*much* easier to deal with and is actually what we want when using it
anyways.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219474 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 79008494c26f1ebd492e3ac6f0c64f35b7eb2ee4..f4be7e1c6e5111f6d8c1d11cd17b67b4c12ecbdc 100644 (file)
@@ -491,20 +491,31 @@ public:
   /// return true.
   bool getExactInverse(APFloat *inv) const;
 
+  /// \brief Enumeration of \c ilogb error results.
+  enum IlogbErrorKinds {
+    IEK_Zero = INT_MIN+1,
+    IEK_NaN = INT_MIN,
+    IEK_Inf = INT_MAX
+  };
+
   /// \brief Returns the exponent of the internal representation of the APFloat.
   ///
   /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
-  friend APFloat logb(const APFloat &Arg) {
-    if (Arg.isZero() || Arg.isNaN())
-      return Arg;
-
+  /// For special APFloat values, this returns special error codes:
+  ///
+  ///   NaN -> \c IEK_NaN
+  ///   0   -> \c IEK_Zero
+  ///   Inf -> \c IEK_Inf
+  ///
+  friend int ilogb(const APFloat &Arg) {
+    if (Arg.isNaN())
+      return IEK_NaN;
+    if (Arg.isZero())
+      return IEK_Zero;
     if (Arg.isInfinity())
-      return APFloat::getInf(Arg.getSemantics());
+      return IEK_Inf;
 
-    APFloat Result(Arg.getSemantics(), std::abs(Arg.exponent));
-    if (Arg.exponent < 0)
-      Result.changeSign();
-    return Result;
+    return Arg.exponent;
   }
 
   /// \brief Returns: X * 2^Exp for integral exponents.
index bc11dab663fdf8ba0164cc8c8079d8269884d4ec..8a29b86b785c7ececff1d27c6176dc8432da65bd 100644 (file)
@@ -2692,55 +2692,33 @@ TEST(APFloatTest, operatorOverloads) {
   EXPECT_TRUE(One.bitwiseIsEqual(Two / Two));
 }
 
-TEST(APFloatTest, logb) {
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "0x0p+0")
-          .bitwiseIsEqual(logb(APFloat(APFloat::IEEEsingle, "0x1p+0"))));
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "0x0p+0")
-          .bitwiseIsEqual(logb(APFloat(APFloat::IEEEsingle, "-0x1p+0"))));
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "0x2Ap+0")
-          .bitwiseIsEqual(logb(APFloat(APFloat::IEEEsingle, "0x1p+42"))));
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "-0x2Ap+0")
-          .bitwiseIsEqual(logb(APFloat(APFloat::IEEEsingle, "0x1p-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 QNaN = APFloat::getNaN(APFloat::IEEEsingle, false);
-  APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle, false);
-
-  EXPECT_TRUE(PInf.bitwiseIsEqual(logb(PInf)));
-  EXPECT_TRUE(PInf.bitwiseIsEqual(logb(MInf)));
-  EXPECT_TRUE(PZero.bitwiseIsEqual(logb(PZero)));
-  EXPECT_TRUE(MZero.bitwiseIsEqual(logb(MZero)));
-  EXPECT_TRUE(QNaN.bitwiseIsEqual(logb(QNaN)));
-  EXPECT_TRUE(SNaN.bitwiseIsEqual(logb(SNaN)));
-
-  APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle, false);
-  APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle, true);
-  APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, false);
-  APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, true);
-  APFloat PSmallestNormalized =
-      APFloat::getSmallestNormalized(APFloat::IEEEsingle, false);
-  APFloat MSmallestNormalized =
-      APFloat::getSmallestNormalized(APFloat::IEEEsingle, true);
-
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "0x7Fp+0").bitwiseIsEqual(logb(PLargestValue)));
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "0x7Fp+0").bitwiseIsEqual(logb(MLargestValue)));
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "-0x7Ep+0").bitwiseIsEqual(logb(PSmallestValue)));
-  EXPECT_TRUE(
-      APFloat(APFloat::IEEEsingle, "-0x7Ep+0").bitwiseIsEqual(logb(MSmallestValue)));
-  EXPECT_TRUE(APFloat(APFloat::IEEEsingle, "-0x7Ep+0")
-                  .bitwiseIsEqual(logb(PSmallestNormalized)));
-  EXPECT_TRUE(APFloat(APFloat::IEEEsingle, "-0x7Ep+0")
-                  .bitwiseIsEqual(logb(MSmallestNormalized)));
+TEST(APFloatTest, ilogb) {
+  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+0")));
+  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "-0x1p+0")));
+  EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+42")));
+  EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p-42")));
+
+  EXPECT_EQ(APFloat::IEK_Inf,
+            ilogb(APFloat::getInf(APFloat::IEEEsingle, false)));
+  EXPECT_EQ(APFloat::IEK_Inf,
+            ilogb(APFloat::getInf(APFloat::IEEEsingle, true)));
+  EXPECT_EQ(APFloat::IEK_Zero,
+            ilogb(APFloat::getZero(APFloat::IEEEsingle, false)));
+  EXPECT_EQ(APFloat::IEK_Zero,
+            ilogb(APFloat::getZero(APFloat::IEEEsingle, true)));
+  EXPECT_EQ(APFloat::IEK_NaN,
+            ilogb(APFloat::getNaN(APFloat::IEEEsingle, false)));
+  EXPECT_EQ(APFloat::IEK_NaN,
+            ilogb(APFloat::getSNaN(APFloat::IEEEsingle, false)));
+
+  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, false)));
+  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, true)));
+  EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false)));
+  EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, true)));
+  EXPECT_EQ(-126,
+            ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, false)));
+  EXPECT_EQ(-126,
+            ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, true)));
 }
 
 TEST(APFloatTest, scalbn) {