diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index f4be7e1c6e5..b3d61a3f325 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -649,6 +649,28 @@ private: hash_code hash_value(const APFloat &Arg); APFloat scalbn(APFloat X, int Exp); +/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat minnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat maxnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + } // namespace llvm #endif // LLVM_ADT_APFLOAT_H diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 8a29b86b785..880e8317084 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -476,6 +476,28 @@ TEST(APFloatTest, FMA) { } } +TEST(APFloatTest, MinNum) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + + EXPECT_EQ(1.0, minnum(f1, f2).convertToDouble()); + EXPECT_EQ(1.0, minnum(f2, f1).convertToDouble()); + EXPECT_EQ(1.0, minnum(f1, nan).convertToDouble()); + EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); +} + +TEST(APFloatTest, MaxNum) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + + EXPECT_EQ(2.0, maxnum(f1, f2).convertToDouble()); + EXPECT_EQ(2.0, maxnum(f2, f1).convertToDouble()); + EXPECT_EQ(1.0, maxnum(f1, nan).convertToDouble()); + EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); +} + TEST(APFloatTest, Denormal) { APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;