Commit 6c61edcb authored by Jay Foad's avatar Jay Foad
Browse files

[APFloat] Overload comparison operators

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
parent 69ec84f8
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -1125,7 +1125,27 @@ public:
  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() &&
+65 −0
Original line number Diff line number Diff line
@@ -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);