[llvm] APFloat: Add minimumnum and maximumnum (PR #96304)
YunQiang Su via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 21 06:29:24 PDT 2024
https://github.com/wzssyqa created https://github.com/llvm/llvm-project/pull/96304
They implements IEEE754-2019 minimumNumber and maximumNumber semantics.
Newer libc also has these 2 function with name
fminimum_num
fmaximum_num
We are planning add minimumnum and maximumnum intrinsic. This is a step to the goal.
>From 30e193b84cb98d81577414a5302dd59764acb13b Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Fri, 21 Jun 2024 21:24:39 +0800
Subject: [PATCH] APFloat: Add minimumnum and maximumnum
They implements IEEE754-2019 minimumNumber and maximumNumber
semantics.
Newer libc also has these 2 function with name
fminimum_num
fmaximum_num
We are planning add minimumnum and maximumnum intrinsic.
This is a step for them.
---
llvm/include/llvm/ADT/APFloat.h | 26 ++++++++++++++++
llvm/unittests/ADT/APFloatTest.cpp | 48 ++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index c24eae8da3797..db2fa480655c6 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1483,6 +1483,19 @@ inline APFloat minimum(const APFloat &A, const APFloat &B) {
return B < A ? B : A;
}
+/// Implements IEEE 754-2019 minimumNumber semantics. Returns the smaller
+/// of 2 arguments, not propagating NaNs and treating -0 as less than +0.
+LLVM_READONLY
+inline APFloat minimumnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B.isNaN() ? B.makeQuiet() : B;
+ if (B.isNaN())
+ return A;
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? A : B;
+ return B < A ? B : A;
+}
+
/// Implements IEEE 754-2019 maximum semantics. Returns the larger of 2
/// arguments, propagating NaNs and treating -0 as less than +0.
LLVM_READONLY
@@ -1496,6 +1509,19 @@ inline APFloat maximum(const APFloat &A, const APFloat &B) {
return A < B ? B : A;
}
+/// Implements IEEE 754-2019 maximumNumber semantics. Returns the larger
+/// of 2 arguments, not propagating NaNs and treating -0 as less than +0.
+LLVM_READONLY
+inline APFloat maximumnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B.isNaN() ? B.makeQuiet() : B;
+ if (B.isNaN())
+ return A;
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? B : A;
+ return A < B ? B : A;
+}
+
// We want the following functions to be available in the header for inlining.
// We cannot define them inline in the class definition of `DoubleAPFloat`
// because doing so would instantiate `std::unique_ptr<APFloat[]>` before
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index f6af4b0e5f651..a105cd81d7431 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -631,6 +631,54 @@ TEST(APFloatTest, Maximum) {
EXPECT_TRUE(std::isnan(maximum(nan, f1).convertToDouble()));
}
+TEST(APFloatTest, MinimumNumber) {
+ APFloat f1(1.0);
+ APFloat f2(2.0);
+ APFloat zp(0.0);
+ APFloat zn(-0.0);
+ APFloat nan = APFloat::getNaN(APFloat::IEEEdouble());
+ APFloat snan = APFloat::getSNaN(APFloat::IEEEdouble());
+
+ EXPECT_EQ(1.0, minimumnum(f1, f2).convertToDouble());
+ EXPECT_EQ(1.0, minimumnum(f2, f1).convertToDouble());
+ EXPECT_EQ(-0.0, minimumnum(zp, zn).convertToDouble());
+ EXPECT_EQ(-0.0, minimumnum(zn, zp).convertToDouble());
+ EXPECT_TRUE(minimumnum(zn, zp).isNegative());
+ EXPECT_TRUE(minimumnum(zp, zn).isNegative());
+ EXPECT_TRUE(minimumnum(zn, zn).isNegative());
+ EXPECT_FALSE(minimumnum(zp, zp).isNegative());
+ EXPECT_FALSE(std::isnan(minimumnum(f1, nan).convertToDouble()));
+ EXPECT_FALSE(std::isnan(minimumnum(nan, f1).convertToDouble()));
+ EXPECT_FALSE(std::isnan(minimumnum(f1, snan).convertToDouble()));
+ EXPECT_FALSE(std::isnan(minimumnum(snan, f1).convertToDouble()));
+ EXPECT_FALSE(minimumnum(snan, nan).isSignaling());
+ EXPECT_FALSE(minimumnum(snan, snan).isSignaling());
+}
+
+TEST(APFloatTest, MaximumNumber) {
+ APFloat f1(1.0);
+ APFloat f2(2.0);
+ APFloat zp(0.0);
+ APFloat zn(-0.0);
+ APFloat nan = APFloat::getNaN(APFloat::IEEEdouble());
+ APFloat snan = APFloat::getSNaN(APFloat::IEEEdouble());
+
+ EXPECT_EQ(2.0, maximumnum(f1, f2).convertToDouble());
+ EXPECT_EQ(2.0, maximumnum(f2, f1).convertToDouble());
+ EXPECT_EQ(0.0, maximumnum(zp, zn).convertToDouble());
+ EXPECT_EQ(0.0, maximumnum(zn, zp).convertToDouble());
+ EXPECT_FALSE(maximumnum(zn, zp).isNegative());
+ EXPECT_FALSE(maximumnum(zp, zn).isNegative());
+ EXPECT_TRUE(maximumnum(zn, zn).isNegative());
+ EXPECT_FALSE(maximumnum(zp, zp).isNegative());
+ EXPECT_FALSE(std::isnan(maximumnum(f1, nan).convertToDouble()));
+ EXPECT_FALSE(std::isnan(maximumnum(nan, f1).convertToDouble()));
+ EXPECT_FALSE(std::isnan(maximumnum(f1, snan).convertToDouble()));
+ EXPECT_FALSE(std::isnan(maximumnum(snan, f1).convertToDouble()));
+ EXPECT_FALSE(maximumnum(snan, nan).isSignaling());
+ EXPECT_FALSE(maximumnum(snan, snan).isSignaling());
+}
+
TEST(APFloatTest, Denormal) {
APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
More information about the llvm-commits
mailing list