Skip to content

Commit

Permalink
[APFloat] Overload comparison operators
Browse files Browse the repository at this point in the history
Summary:
These implement the usual IEEE-style floating point comparison
semantics, e.g. +0.0 == -0.0 and all operators except != return false
if either argument is NaN.

Subscribers: arsenm, jvesely, nhaehnle, hiraditya, dexonsmith, kerbowa, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D75237
  • Loading branch information
jayfoad committed Mar 6, 2020
1 parent 69ec84f commit 6c61edc
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
22 changes: 21 additions & 1 deletion llvm/include/llvm/ADT/APFloat.h
Expand Up @@ -1125,7 +1125,27 @@ class APFloat : public APFloatBase {
double convertToDouble() const { return getIEEE().convertToDouble(); }
float convertToFloat() const { return getIEEE().convertToFloat(); }

bool operator==(const APFloat &) const = delete;
bool operator==(const APFloat &RHS) const { return compare(RHS) == cmpEqual; }

bool operator!=(const APFloat &RHS) const { return compare(RHS) != cmpEqual; }

bool operator<(const APFloat &RHS) const {
return compare(RHS) == cmpLessThan;
}

bool operator>(const APFloat &RHS) const {
return compare(RHS) == cmpGreaterThan;
}

bool operator<=(const APFloat &RHS) const {
cmpResult Res = compare(RHS);
return Res == cmpLessThan || Res == cmpEqual;
}

bool operator>=(const APFloat &RHS) const {
cmpResult Res = compare(RHS);
return Res == cmpGreaterThan || Res == cmpEqual;
}

cmpResult compare(const APFloat &RHS) const {
assert(&getSemantics() == &RHS.getSemantics() &&
Expand Down
65 changes: 65 additions & 0 deletions llvm/unittests/ADT/APFloatTest.cpp
Expand Up @@ -2932,6 +2932,71 @@ TEST(APFloatTest, operatorOverloads) {
EXPECT_TRUE(One.bitwiseIsEqual(Two / Two));
}

TEST(APFloatTest, Comparisons) {
enum {MNan, MInf, MBig, MOne, MZer, PZer, POne, PBig, PInf, PNan, NumVals};
APFloat Vals[NumVals] = {
APFloat::getNaN(APFloat::IEEEsingle(), true),
APFloat::getInf(APFloat::IEEEsingle(), true),
APFloat::getLargest(APFloat::IEEEsingle(), true),
APFloat(APFloat::IEEEsingle(), "-0x1p+0"),
APFloat::getZero(APFloat::IEEEsingle(), true),
APFloat::getZero(APFloat::IEEEsingle(), false),
APFloat(APFloat::IEEEsingle(), "0x1p+0"),
APFloat::getLargest(APFloat::IEEEsingle(), false),
APFloat::getInf(APFloat::IEEEsingle(), false),
APFloat::getNaN(APFloat::IEEEsingle(), false),
};
using Relation = void (*)(const APFloat &, const APFloat &);
Relation LT = [](const APFloat &LHS, const APFloat &RHS) {
EXPECT_FALSE(LHS == RHS);
EXPECT_TRUE(LHS != RHS);
EXPECT_TRUE(LHS < RHS);
EXPECT_FALSE(LHS > RHS);
EXPECT_TRUE(LHS <= RHS);
EXPECT_FALSE(LHS >= RHS);
};
Relation EQ = [](const APFloat &LHS, const APFloat &RHS) {
EXPECT_TRUE(LHS == RHS);
EXPECT_FALSE(LHS != RHS);
EXPECT_FALSE(LHS < RHS);
EXPECT_FALSE(LHS > RHS);
EXPECT_TRUE(LHS <= RHS);
EXPECT_TRUE(LHS >= RHS);
};
Relation GT = [](const APFloat &LHS, const APFloat &RHS) {
EXPECT_FALSE(LHS == RHS);
EXPECT_TRUE(LHS != RHS);
EXPECT_FALSE(LHS < RHS);
EXPECT_TRUE(LHS > RHS);
EXPECT_FALSE(LHS <= RHS);
EXPECT_TRUE(LHS >= RHS);
};
Relation UN = [](const APFloat &LHS, const APFloat &RHS) {
EXPECT_FALSE(LHS == RHS);
EXPECT_TRUE(LHS != RHS);
EXPECT_FALSE(LHS < RHS);
EXPECT_FALSE(LHS > RHS);
EXPECT_FALSE(LHS <= RHS);
EXPECT_FALSE(LHS >= RHS);
};
Relation Relations[NumVals][NumVals] = {
// -N -I -B -1 -0 +0 +1 +B +I +N
/* MNan */ {UN, UN, UN, UN, UN, UN, UN, UN, UN, UN},
/* MInf */ {UN, EQ, LT, LT, LT, LT, LT, LT, LT, UN},
/* MBig */ {UN, GT, EQ, LT, LT, LT, LT, LT, LT, UN},
/* MOne */ {UN, GT, GT, EQ, LT, LT, LT, LT, LT, UN},
/* MZer */ {UN, GT, GT, GT, EQ, EQ, LT, LT, LT, UN},
/* PZer */ {UN, GT, GT, GT, EQ, EQ, LT, LT, LT, UN},
/* POne */ {UN, GT, GT, GT, GT, GT, EQ, LT, LT, UN},
/* PBig */ {UN, GT, GT, GT, GT, GT, GT, EQ, LT, UN},
/* PInf */ {UN, GT, GT, GT, GT, GT, GT, GT, EQ, UN},
/* PNan */ {UN, UN, UN, UN, UN, UN, UN, UN, UN, UN},
};
for (unsigned I = 0; I < NumVals; ++I)
for (unsigned J = 0; J < NumVals; ++J)
Relations[I][J](Vals[I], Vals[J]);
}

TEST(APFloatTest, abs) {
APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
Expand Down

0 comments on commit 6c61edc

Please sign in to comment.