OSDN Git Service

APFloat: Fix ilogb for denormals
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Sun, 13 Mar 2016 05:12:32 +0000 (05:12 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Sun, 13 Mar 2016 05:12:32 +0000 (05:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263370 91177308-0d34-0410-b5e6-96231b3b80d8

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

index a1376ad..45daeca 100644 (file)
@@ -511,16 +511,7 @@ public:
   ///   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 IEK_Inf;
-
-    return Arg.exponent;
-  }
+  friend int ilogb(const APFloat &Arg);
 
   /// \brief Returns: X * 2^Exp for integral exponents.
   friend APFloat scalbn(APFloat X, int Exp, roundingMode);
index 95953b6..814c72c 100644 (file)
@@ -3945,6 +3945,24 @@ APFloat::makeZero(bool Negative) {
   APInt::tcSet(significandParts(), 0, partCount());  
 }
 
+int llvm::ilogb(const APFloat &Arg) {
+  if (Arg.isNaN())
+    return APFloat::IEK_NaN;
+  if (Arg.isZero())
+    return APFloat::IEK_Zero;
+  if (Arg.isInfinity())
+    return APFloat::IEK_Inf;
+  if (!Arg.isDenormal())
+    return Arg.exponent;
+
+  APFloat Normalized(Arg);
+  int SignificandBits = Arg.getSemantics().precision - 1;
+
+  Normalized.exponent += SignificandBits;
+  Normalized.normalize(APFloat::rmNearestTiesToEven, lfExactlyZero);
+  return Normalized.exponent - SignificandBits;
+}
+
 APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) {
   auto MaxExp = X.getSemantics().maxExponent;
   auto MinExp = X.getSemantics().minExponent;
index 546973c..e78caf3 100644 (file)
@@ -2821,6 +2821,19 @@ TEST(APFloatTest, abs) {
 }
 
 TEST(APFloatTest, ilogb) {
+  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble, false)));
+  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble, true)));
+  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-1024")));
+  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-1023")));
+  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "-0x1.ffffffffffffep-1023")));
+  EXPECT_EQ(-51, ilogb(APFloat(APFloat::IEEEdouble, "0x1p-51")));
+  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp-1023")));
+  EXPECT_EQ(-2, ilogb(APFloat(APFloat::IEEEdouble, "0x0.ffffp-1")));
+  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.fffep-1023")));
+  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble, false)));
+  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble, true)));
+
+
   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")));
@@ -2841,8 +2854,9 @@ TEST(APFloatTest, ilogb) {
 
   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(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false)));
+  EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, true)));
   EXPECT_EQ(-126,
             ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, false)));
   EXPECT_EQ(-126,