diff options
author | YunQiang Su <syq@debian.org> | 2024-06-26 07:10:43 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-26 07:10:43 +0800 |
commit | 0d533665054c3a04681c46f3ed88960f28777be1 (patch) | |
tree | 226585cd8fac85ee330223690226df5f909a2af1 /llvm/unittests/ADT/APFloatTest.cpp | |
parent | 847235bbef153c6d805d415cea8494297eaf2bdb (diff) | |
download | llvm-0d533665054c3a04681c46f3ed88960f28777be1.zip llvm-0d533665054c3a04681c46f3ed88960f28777be1.tar.gz llvm-0d533665054c3a04681c46f3ed88960f28777be1.tar.bz2 |
APFloat: Add minimumnum and maximumnum (#96304)
They implements IEEE754-2019 minimumNumber and maximumNumber semantics.
Newer libc also has these 2 functions with names
fminimum_num
fmaximum_num
We are planning add minimumnum and maximumnum intrinsic. This is a step
to the goal.
Diffstat (limited to 'llvm/unittests/ADT/APFloatTest.cpp')
-rw-r--r-- | llvm/unittests/ADT/APFloatTest.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index f6af4b0..cf6bbd31 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -631,6 +631,100 @@ 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); + APInt intPayload_89ab(64, 0x89ab); + APInt intPayload_cdef(64, 0xcdef); + APFloat nan_0123[2] = {APFloat::getNaN(APFloat::IEEEdouble(), false, 0x0123), + APFloat::getNaN(APFloat::IEEEdouble(), false, 0x0123)}; + APFloat mnan_4567[2] = {APFloat::getNaN(APFloat::IEEEdouble(), true, 0x4567), + APFloat::getNaN(APFloat::IEEEdouble(), true, 0x4567)}; + APFloat nan_89ab[2] = { + APFloat::getSNaN(APFloat::IEEEdouble(), false, &intPayload_89ab), + APFloat::getNaN(APFloat::IEEEdouble(), false, 0x89ab)}; + APFloat mnan_cdef[2] = { + APFloat::getSNaN(APFloat::IEEEdouble(), true, &intPayload_cdef), + APFloat::getNaN(APFloat::IEEEdouble(), true, 0xcdef)}; + + EXPECT_TRUE(f1.bitwiseIsEqual(minimumnum(f1, f2))); + EXPECT_TRUE(f1.bitwiseIsEqual(minimumnum(f2, f1))); + EXPECT_TRUE(zn.bitwiseIsEqual(minimumnum(zp, zn))); + EXPECT_TRUE(zn.bitwiseIsEqual(minimumnum(zn, zp))); + + EXPECT_TRUE(minimumnum(zn, zp).isNegative()); + EXPECT_TRUE(minimumnum(zp, zn).isNegative()); + EXPECT_TRUE(minimumnum(zn, zn).isNegative()); + EXPECT_FALSE(minimumnum(zp, zp).isNegative()); + + for (APFloat n : {nan_0123[0], mnan_4567[0], nan_89ab[0], mnan_cdef[0]}) + for (APFloat f : {f1, f2, zn, zp}) { + APFloat res = minimumnum(f, n); + EXPECT_FALSE(res.isNaN()); + EXPECT_TRUE(res.bitwiseIsEqual(f)); + res = minimumnum(n, f); + EXPECT_FALSE(res.isNaN()); + EXPECT_TRUE(res.bitwiseIsEqual(f)); + } + + // When NaN vs NaN, we should keep payload/sign of either one. + for (auto n1 : {nan_0123, mnan_4567, nan_89ab, mnan_cdef}) + for (auto n2 : {nan_0123, mnan_4567, nan_89ab, mnan_cdef}) { + APFloat res = minimumnum(n1[0], n2[0]); + EXPECT_TRUE(res.bitwiseIsEqual(n1[1]) || res.bitwiseIsEqual(n2[1])); + EXPECT_FALSE(res.isSignaling()); + } +} + +TEST(APFloatTest, MaximumNumber) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat zp(0.0); + APFloat zn(-0.0); + APInt intPayload_89ab(64, 0x89ab); + APInt intPayload_cdef(64, 0xcdef); + APFloat nan_0123[2] = {APFloat::getNaN(APFloat::IEEEdouble(), false, 0x0123), + APFloat::getNaN(APFloat::IEEEdouble(), false, 0x0123)}; + APFloat mnan_4567[2] = {APFloat::getNaN(APFloat::IEEEdouble(), true, 0x4567), + APFloat::getNaN(APFloat::IEEEdouble(), true, 0x4567)}; + APFloat nan_89ab[2] = { + APFloat::getSNaN(APFloat::IEEEdouble(), false, &intPayload_89ab), + APFloat::getNaN(APFloat::IEEEdouble(), false, 0x89ab)}; + APFloat mnan_cdef[2] = { + APFloat::getSNaN(APFloat::IEEEdouble(), true, &intPayload_cdef), + APFloat::getNaN(APFloat::IEEEdouble(), true, 0xcdef)}; + + EXPECT_TRUE(f2.bitwiseIsEqual(maximumnum(f1, f2))); + EXPECT_TRUE(f2.bitwiseIsEqual(maximumnum(f2, f1))); + EXPECT_TRUE(zp.bitwiseIsEqual(maximumnum(zp, zn))); + EXPECT_TRUE(zp.bitwiseIsEqual(maximumnum(zn, zp))); + + EXPECT_FALSE(maximumnum(zn, zp).isNegative()); + EXPECT_FALSE(maximumnum(zp, zn).isNegative()); + EXPECT_TRUE(maximumnum(zn, zn).isNegative()); + EXPECT_FALSE(maximumnum(zp, zp).isNegative()); + + for (APFloat n : {nan_0123[0], mnan_4567[0], nan_89ab[0], mnan_cdef[0]}) + for (APFloat f : {f1, f2, zn, zp}) { + APFloat res = maximumnum(f, n); + EXPECT_FALSE(res.isNaN()); + EXPECT_TRUE(res.bitwiseIsEqual(f)); + res = maximumnum(n, f); + EXPECT_FALSE(res.isNaN()); + EXPECT_TRUE(res.bitwiseIsEqual(f)); + } + + // When NaN vs NaN, we should keep payload/sign of either one. + for (auto n1 : {nan_0123, mnan_4567, nan_89ab, mnan_cdef}) + for (auto n2 : {nan_0123, mnan_4567, nan_89ab, mnan_cdef}) { + APFloat res = maximumnum(n1[0], n2[0]); + EXPECT_TRUE(res.bitwiseIsEqual(n1[1]) || res.bitwiseIsEqual(n2[1])); + EXPECT_FALSE(res.isSignaling()); + } +} + TEST(APFloatTest, Denormal) { APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven; |