From f4ec6697b8aecadc8510c10f536ecacd53b6c981 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Fri, 10 Oct 2014 05:14:12 +0000 Subject: [PATCH] [ADT] Replace the logb implementation with the simpler and much closer 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 | 29 +++++++++----- unittests/ADT/APFloatTest.cpp | 72 ++++++++++++----------------------- 2 files changed, 45 insertions(+), 56 deletions(-) diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 79008494c26..f4be7e1c6e5 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -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. diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index bc11dab663f..8a29b86b785 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -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")))); +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"))); - 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_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_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))); + 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) {