Skip to content

Commit

Permalink
[ADT] Replace the logb implementation with the simpler and much closer
Browse files Browse the repository at this point in the history
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
  • Loading branch information
chandlerc committed Oct 10, 2014
1 parent cb84b21 commit f4ec669
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 58 deletions.
29 changes: 20 additions & 9 deletions include/llvm/ADT/APFloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,20 +491,31 @@ class APFloat {
/// 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.
Expand Down
76 changes: 27 additions & 49 deletions unittests/ADT/APFloatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit f4ec669

Please sign in to comment.