[libc-commits] [libc] f5dcfb9 - [libc][math][c23] Add {totalorder, totalordermag}f16 C23 math functions (#95014)
via libc-commits
libc-commits at lists.llvm.org
Tue Jun 11 08:04:54 PDT 2024
Author: OverMighty
Date: 2024-06-11T11:04:48-04:00
New Revision: f5dcfb9968a3d4945b5fa7d142044c29c9a9f175
URL: https://github.com/llvm/llvm-project/commit/f5dcfb9968a3d4945b5fa7d142044c29c9a9f175
DIFF: https://github.com/llvm/llvm-project/commit/f5dcfb9968a3d4945b5fa7d142044c29c9a9f175.diff
LOG: [libc][math][c23] Add {totalorder,totalordermag}f16 C23 math functions (#95014)
Part of #93566.
Added:
libc/src/math/generic/totalorderf16.cpp
libc/src/math/generic/totalordermagf16.cpp
libc/src/math/totalorderf16.h
libc/src/math/totalordermagf16.h
libc/test/src/math/smoke/TotalOrderMagTest.h
libc/test/src/math/smoke/TotalOrderTest.h
libc/test/src/math/smoke/totalorderf16_test.cpp
libc/test/src/math/smoke/totalordermagf16_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/docs/c23.rst
libc/docs/math/index.rst
libc/spec/stdc.td
libc/src/__support/FPUtil/BasicOperations.h
libc/src/math/CMakeLists.txt
libc/src/math/generic/CMakeLists.txt
libc/test/UnitTest/FPMatcher.h
libc/test/src/math/smoke/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 381061ce3fcbf..db96a80051a8d 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -541,6 +541,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
+ libc.src.math.totalorderf16
+ libc.src.math.totalordermagf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
libc.src.math.ufromfpxf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e99960b12441d..355eaf33ace6d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -571,6 +571,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
+ libc.src.math.totalorderf16
+ libc.src.math.totalordermagf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
libc.src.math.ufromfpxf16
diff --git a/libc/docs/c23.rst b/libc/docs/c23.rst
index fec9b24bbd581..4134befd1ed35 100644
--- a/libc/docs/c23.rst
+++ b/libc/docs/c23.rst
@@ -42,8 +42,8 @@ Additions:
* rsqrt*
* __STDC_IEC_60559_DFP__ functions (_Decimal32, _Decimal64, _Decimal128)
* compoundn*
- * totalorder*
- * totalordermag*
+ * totalorder* |check|
+ * totalordermag* |check|
* getpayload*
* setpayload*
* iscannonical
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index f83a646c34b57..d556885eda622 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -210,6 +210,10 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| scalbn | |check| | |check| | |check| | | |check| | 7.12.6.19 | F.10.3.19 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| totalorder | | | | |check| | | F.10.12.1 | N/A |
++------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| totalordermag | | | | |check| | | F.10.12.2 | N/A |
++------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| trunc | |check| | |check| | |check| | |check| | |check| | 7.12.9.9 | F.10.6.9 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| ufromfp | |check| | |check| | |check| | |check| | |check| | 7.12.9.10 | F.10.6.10 |
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 34169948fc6d2..b134ec00a7d7a 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -710,6 +710,10 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"canonicalizel", RetValSpec<IntType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"canonicalizef16", RetValSpec<IntType>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"canonicalizef128", RetValSpec<IntType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
+
+ GuardedFunctionSpec<"totalorderf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
+
+ GuardedFunctionSpec<"totalordermagf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
]
>;
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index e5ac101fedc0e..beb8e48db8f51 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -240,6 +240,31 @@ LIBC_INLINE int canonicalize(T &cx, const T &x) {
return 0;
}
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+totalorder(T x, T y) {
+ using FPBits = FPBits<T>;
+ FPBits x_bits(x);
+ FPBits y_bits(y);
+
+ using StorageType = typename FPBits::StorageType;
+ StorageType x_u = x_bits.uintval();
+ StorageType y_u = y_bits.uintval();
+
+ using signed_t = cpp::make_signed_t<StorageType>;
+ signed_t x_signed = static_cast<signed_t>(x_u);
+ signed_t y_signed = static_cast<signed_t>(y_u);
+
+ bool both_neg = (x_u & y_u & FPBits::SIGN_MASK) != 0;
+ return x_signed == y_signed || ((x_signed <= y_signed) != both_neg);
+}
+
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+totalordermag(T x, T y) {
+ return FPBits<T>(x).abs().uintval() <= FPBits<T>(y).abs().uintval();
+}
+
} // namespace fputil
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 82dfdaf479ff0..2446c293b8ef5 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -369,6 +369,10 @@ add_math_entrypoint_object(tanhf)
add_math_entrypoint_object(tgamma)
add_math_entrypoint_object(tgammaf)
+add_math_entrypoint_object(totalorderf16)
+
+add_math_entrypoint_object(totalordermagf16)
+
add_math_entrypoint_object(trunc)
add_math_entrypoint_object(truncf)
add_math_entrypoint_object(truncl)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index f4f683e61bd65..673bef516b13d 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3577,3 +3577,27 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
)
+
+add_entrypoint_object(
+ totalorderf16
+ SRCS
+ totalorderf16.cpp
+ HDRS
+ ../totalorderf16.h
+ DEPENDS
+ libc.src.__support.FPUtil.basic_operations
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ totalordermagf16
+ SRCS
+ totalordermagf16.cpp
+ HDRS
+ ../totalordermagf16.h
+ DEPENDS
+ libc.src.__support.FPUtil.basic_operations
+ COMPILE_OPTIONS
+ -O3
+)
diff --git a/libc/src/math/generic/totalorderf16.cpp b/libc/src/math/generic/totalorderf16.cpp
new file mode 100644
index 0000000000000..e43beb33d2fd3
--- /dev/null
+++ b/libc/src/math/generic/totalorderf16.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of totalorderf16 function --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/totalorderf16.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, totalorderf16, (const float16 *x, const float16 *y)) {
+ return static_cast<int>(fputil::totalorder(*x, *y));
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/totalordermagf16.cpp b/libc/src/math/generic/totalordermagf16.cpp
new file mode 100644
index 0000000000000..09d04fbeb2d2c
--- /dev/null
+++ b/libc/src/math/generic/totalordermagf16.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of totalordermagf16 function -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/totalordermagf16.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, totalordermagf16,
+ (const float16 *x, const float16 *y)) {
+ return static_cast<int>(fputil::totalordermag(*x, *y));
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/totalorderf16.h b/libc/src/math/totalorderf16.h
new file mode 100644
index 0000000000000..f5390140c4dc2
--- /dev/null
+++ b/libc/src/math/totalorderf16.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for totalorderf16 -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_TOTALORDERF16_H
+#define LLVM_LIBC_SRC_MATH_TOTALORDERF16_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+int totalorderf16(const float16 *x, const float16 *y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_TOTALORDERF16_H
diff --git a/libc/src/math/totalordermagf16.h b/libc/src/math/totalordermagf16.h
new file mode 100644
index 0000000000000..8c6621b9783df
--- /dev/null
+++ b/libc/src/math/totalordermagf16.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for totalordermagf16 --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H
+#define LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+int totalordermagf16(const float16 *x, const float16 *y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index 26af5cec02b58..86b823260e197 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -97,8 +97,10 @@ template <typename T> struct FPTest : public Test {
LIBC_NAMESPACE::cpp::numeric_limits<StorageType>::max(); \
const T zero = FPBits::zero(Sign::POS).get_val(); \
const T neg_zero = FPBits::zero(Sign::NEG).get_val(); \
- const T aNaN = FPBits::quiet_nan().get_val(); \
- const T sNaN = FPBits::signaling_nan().get_val(); \
+ const T aNaN = FPBits::quiet_nan(Sign::POS).get_val(); \
+ const T neg_aNaN = FPBits::quiet_nan(Sign::NEG).get_val(); \
+ const T sNaN = FPBits::signaling_nan(Sign::POS).get_val(); \
+ const T neg_sNaN = FPBits::signaling_nan(Sign::NEG).get_val(); \
const T inf = FPBits::inf(Sign::POS).get_val(); \
const T neg_inf = FPBits::inf(Sign::NEG).get_val(); \
const T min_normal = FPBits::min_normal().get_val(); \
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 75e2bdd7be100..68cd412b14e9d 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3519,3 +3519,27 @@ add_fp_unittest(
libc.src.math.powf
libc.src.__support.FPUtil.fp_bits
)
+
+add_fp_unittest(
+ totalorderf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ totalorderf16_test.cpp
+ HDRS
+ TotalOrderTest.h
+ DEPENDS
+ libc.src.math.totalorderf16
+)
+
+add_fp_unittest(
+ totalordermagf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ totalordermagf16_test.cpp
+ HDRS
+ TotalOrderMagTest.h
+ DEPENDS
+ libc.src.math.totalordermagf16
+)
diff --git a/libc/test/src/math/smoke/TotalOrderMagTest.h b/libc/test/src/math/smoke/TotalOrderMagTest.h
new file mode 100644
index 0000000000000..5fe2983a0e678
--- /dev/null
+++ b/libc/test/src/math/smoke/TotalOrderMagTest.h
@@ -0,0 +1,142 @@
+//===-- Utility class to test flavors of totalordermag ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERMAGTEST_H
+#define LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERMAGTEST_H
+
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T>
+class TotalOrderMagTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+ DECLARE_SPECIAL_CONSTANTS(T)
+
+public:
+ typedef int (*TotalOrderMagFunc)(const T *, const T *);
+
+ bool funcWrapper(TotalOrderMagFunc func, T x, T y) {
+ return func(&x, &y) != 0;
+ }
+
+ void testXLesserThanY(TotalOrderMagFunc func) {
+ EXPECT_TRUE(funcWrapper(func, neg_inf, inf));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(123.38)));
+
+ EXPECT_FALSE(funcWrapper(func, T(-0.1), T(0.0)));
+ EXPECT_FALSE(funcWrapper(func, T(-123.38), T(0.0)));
+
+ EXPECT_TRUE(funcWrapper(func, T(-0.1), T(0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(-123.38), T(123.38)));
+ }
+
+ void testXGreaterThanY(TotalOrderMagFunc func) {
+ EXPECT_TRUE(funcWrapper(func, inf, neg_inf));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(-0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(-123.38)));
+
+ EXPECT_FALSE(funcWrapper(func, T(0.1), T(0.0)));
+ EXPECT_FALSE(funcWrapper(func, T(123.38), T(0.0)));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.1), T(-0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(123.38), T(-123.38)));
+ }
+
+ void testXEqualToY(TotalOrderMagFunc func) {
+ EXPECT_TRUE(funcWrapper(func, inf, inf));
+ EXPECT_TRUE(funcWrapper(func, neg_inf, neg_inf));
+
+ EXPECT_TRUE(funcWrapper(func, T(-0.0), T(0.0)));
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(-0.0)));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.0)));
+ EXPECT_TRUE(funcWrapper(func, T(-0.0), T(-0.0)));
+ EXPECT_TRUE(funcWrapper(func, T(0.1), T(0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(-0.1), T(-0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(123.38), T(123.38)));
+ EXPECT_TRUE(funcWrapper(func, T(-123.38), T(-123.38)));
+ }
+
+ void testSingleNaN(TotalOrderMagFunc func) {
+ EXPECT_FALSE(funcWrapper(func, neg_aNaN, T(0.0)));
+ EXPECT_FALSE(funcWrapper(func, neg_aNaN, T(0.1)));
+ EXPECT_FALSE(funcWrapper(func, neg_aNaN, T(123.38)));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, T(0.1), neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, T(123.38), neg_aNaN));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), aNaN));
+ EXPECT_TRUE(funcWrapper(func, T(0.1), aNaN));
+ EXPECT_TRUE(funcWrapper(func, T(123.38), aNaN));
+
+ EXPECT_FALSE(funcWrapper(func, aNaN, T(0.0)));
+ EXPECT_FALSE(funcWrapper(func, aNaN, T(0.1)));
+ EXPECT_FALSE(funcWrapper(func, aNaN, T(123.38)));
+ }
+
+ void testNaNSigns(TotalOrderMagFunc func) {
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, aNaN));
+ EXPECT_FALSE(funcWrapper(func, neg_aNaN, sNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, aNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, sNaN));
+
+ EXPECT_TRUE(funcWrapper(func, aNaN, neg_aNaN));
+ EXPECT_FALSE(funcWrapper(func, aNaN, neg_sNaN));
+ EXPECT_TRUE(funcWrapper(func, sNaN, neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, sNaN, neg_sNaN));
+ }
+
+ void testQuietVsSignalingNaN(TotalOrderMagFunc func) {
+ EXPECT_FALSE(funcWrapper(func, neg_aNaN, neg_sNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, sNaN, aNaN));
+ EXPECT_FALSE(funcWrapper(func, aNaN, sNaN));
+ }
+
+ void testNaNPayloads(TotalOrderMagFunc func) {
+ T qnan_123 = FPBits::quiet_nan(Sign::POS, 0x123).get_val();
+ T neg_qnan_123 = FPBits::quiet_nan(Sign::NEG, 0x123).get_val();
+ T snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val();
+ T neg_snan_123 = FPBits::signaling_nan(Sign::NEG, 0x123).get_val();
+
+ EXPECT_TRUE(funcWrapper(func, aNaN, aNaN));
+ EXPECT_TRUE(funcWrapper(func, sNaN, sNaN));
+ EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123));
+ EXPECT_TRUE(funcWrapper(func, sNaN, snan_123));
+ EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN));
+ EXPECT_FALSE(funcWrapper(func, snan_123, sNaN));
+
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_qnan_123));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_snan_123));
+ EXPECT_FALSE(funcWrapper(func, neg_qnan_123, neg_aNaN));
+ EXPECT_FALSE(funcWrapper(func, neg_snan_123, neg_sNaN));
+ }
+};
+
+#define LIST_TOTALORDERMAG_TESTS(T, func) \
+ using LlvmLibcTotalOrderMagTest = TotalOrderMagTestTemplate<T>; \
+ TEST_F(LlvmLibcTotalOrderMagTest, XLesserThanY) { testXLesserThanY(&func); } \
+ TEST_F(LlvmLibcTotalOrderMagTest, XGreaterThanY) { \
+ testXGreaterThanY(&func); \
+ } \
+ TEST_F(LlvmLibcTotalOrderMagTest, XEqualToY) { testXEqualToY(&func); } \
+ TEST_F(LlvmLibcTotalOrderMagTest, SingleNaN) { testSingleNaN(&func); } \
+ TEST_F(LlvmLibcTotalOrderMagTest, NaNSigns) { testNaNSigns(&func); } \
+ TEST_F(LlvmLibcTotalOrderMagTest, QuietVsSignalingNaN) { \
+ testQuietVsSignalingNaN(&func); \
+ } \
+ TEST_F(LlvmLibcTotalOrderMagTest, NaNPayloads) { testNaNPayloads(&func); }
+
+#endif // LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERMAGTEST_H
diff --git a/libc/test/src/math/smoke/TotalOrderTest.h b/libc/test/src/math/smoke/TotalOrderTest.h
new file mode 100644
index 0000000000000..281b2a59f930d
--- /dev/null
+++ b/libc/test/src/math/smoke/TotalOrderTest.h
@@ -0,0 +1,138 @@
+//===-- Utility class to test
diff erent flavors of totalorder ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERTEST_H
+#define LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERTEST_H
+
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T>
+class TotalOrderTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+ DECLARE_SPECIAL_CONSTANTS(T)
+
+public:
+ typedef int (*TotalOrderFunc)(const T *, const T *);
+
+ bool funcWrapper(TotalOrderFunc func, T x, T y) { return func(&x, &y) != 0; }
+
+ void testXLesserThanY(TotalOrderFunc func) {
+ EXPECT_TRUE(funcWrapper(func, neg_inf, inf));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(123.38)));
+
+ EXPECT_TRUE(funcWrapper(func, T(-0.1), T(0.0)));
+ EXPECT_TRUE(funcWrapper(func, T(-123.38), T(0.0)));
+
+ EXPECT_TRUE(funcWrapper(func, T(-0.1), T(0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(-123.38), T(123.38)));
+ }
+
+ void testXGreaterThanY(TotalOrderFunc func) {
+ EXPECT_FALSE(funcWrapper(func, inf, neg_inf));
+
+ EXPECT_FALSE(funcWrapper(func, T(0.0), T(-0.1)));
+ EXPECT_FALSE(funcWrapper(func, T(0.0), T(-123.38)));
+
+ EXPECT_FALSE(funcWrapper(func, T(0.1), T(0.0)));
+ EXPECT_FALSE(funcWrapper(func, T(123.38), T(0.0)));
+
+ EXPECT_FALSE(funcWrapper(func, T(0.1), T(-0.1)));
+ EXPECT_FALSE(funcWrapper(func, T(123.38), T(-123.38)));
+ }
+
+ void testXEqualToY(TotalOrderFunc func) {
+ EXPECT_TRUE(funcWrapper(func, inf, inf));
+ EXPECT_TRUE(funcWrapper(func, neg_inf, neg_inf));
+
+ EXPECT_TRUE(funcWrapper(func, T(-0.0), T(0.0)));
+ EXPECT_FALSE(funcWrapper(func, T(0.0), T(-0.0)));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.0)));
+ EXPECT_TRUE(funcWrapper(func, T(-0.0), T(-0.0)));
+ EXPECT_TRUE(funcWrapper(func, T(0.1), T(0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(-0.1), T(-0.1)));
+ EXPECT_TRUE(funcWrapper(func, T(123.38), T(123.38)));
+ EXPECT_TRUE(funcWrapper(func, T(-123.38), T(-123.38)));
+ }
+
+ void testSingleNaN(TotalOrderFunc func) {
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, T(0.0)));
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, T(0.1)));
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, T(123.38)));
+
+ EXPECT_FALSE(funcWrapper(func, T(0.0), neg_aNaN));
+ EXPECT_FALSE(funcWrapper(func, T(0.1), neg_aNaN));
+ EXPECT_FALSE(funcWrapper(func, T(123.38), neg_aNaN));
+
+ EXPECT_TRUE(funcWrapper(func, T(0.0), aNaN));
+ EXPECT_TRUE(funcWrapper(func, T(0.1), aNaN));
+ EXPECT_TRUE(funcWrapper(func, T(123.38), aNaN));
+
+ EXPECT_FALSE(funcWrapper(func, aNaN, T(0.0)));
+ EXPECT_FALSE(funcWrapper(func, aNaN, T(0.1)));
+ EXPECT_FALSE(funcWrapper(func, aNaN, T(123.38)));
+ }
+
+ void testNaNSigns(TotalOrderFunc func) {
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, aNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, sNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, aNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, sNaN));
+
+ EXPECT_FALSE(funcWrapper(func, aNaN, neg_aNaN));
+ EXPECT_FALSE(funcWrapper(func, aNaN, neg_sNaN));
+ EXPECT_FALSE(funcWrapper(func, sNaN, neg_aNaN));
+ EXPECT_FALSE(funcWrapper(func, sNaN, neg_sNaN));
+ }
+
+ void testQuietVsSignalingNaN(TotalOrderFunc func) {
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_sNaN));
+ EXPECT_FALSE(funcWrapper(func, neg_sNaN, neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, sNaN, aNaN));
+ EXPECT_FALSE(funcWrapper(func, aNaN, sNaN));
+ }
+
+ void testNaNPayloads(TotalOrderFunc func) {
+ T qnan_123 = FPBits::quiet_nan(Sign::POS, 0x123).get_val();
+ T neg_qnan_123 = FPBits::quiet_nan(Sign::NEG, 0x123).get_val();
+ T snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val();
+ T neg_snan_123 = FPBits::signaling_nan(Sign::NEG, 0x123).get_val();
+
+ EXPECT_TRUE(funcWrapper(func, aNaN, aNaN));
+ EXPECT_TRUE(funcWrapper(func, sNaN, sNaN));
+ EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123));
+ EXPECT_TRUE(funcWrapper(func, sNaN, snan_123));
+ EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN));
+ EXPECT_FALSE(funcWrapper(func, snan_123, sNaN));
+
+ EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN));
+ EXPECT_FALSE(funcWrapper(func, neg_aNaN, neg_qnan_123));
+ EXPECT_FALSE(funcWrapper(func, neg_sNaN, neg_snan_123));
+ EXPECT_TRUE(funcWrapper(func, neg_qnan_123, neg_aNaN));
+ EXPECT_TRUE(funcWrapper(func, neg_snan_123, neg_sNaN));
+ }
+};
+
+#define LIST_TOTALORDER_TESTS(T, func) \
+ using LlvmLibcTotalOrderTest = TotalOrderTestTemplate<T>; \
+ TEST_F(LlvmLibcTotalOrderTest, XLesserThanY) { testXLesserThanY(&func); } \
+ TEST_F(LlvmLibcTotalOrderTest, XGreaterThanY) { testXGreaterThanY(&func); } \
+ TEST_F(LlvmLibcTotalOrderTest, XEqualToY) { testXEqualToY(&func); } \
+ TEST_F(LlvmLibcTotalOrderTest, SingleNaN) { testSingleNaN(&func); } \
+ TEST_F(LlvmLibcTotalOrderTest, NaNSigns) { testNaNSigns(&func); } \
+ TEST_F(LlvmLibcTotalOrderTest, QuietVsSignalingNaN) { \
+ testQuietVsSignalingNaN(&func); \
+ } \
+ TEST_F(LlvmLibcTotalOrderTest, NaNPayloads) { testNaNPayloads(&func); }
+
+#endif // LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERTEST_H
diff --git a/libc/test/src/math/smoke/totalorderf16_test.cpp b/libc/test/src/math/smoke/totalorderf16_test.cpp
new file mode 100644
index 0000000000000..410c70c47c51d
--- /dev/null
+++ b/libc/test/src/math/smoke/totalorderf16_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for totalorderf16 ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TotalOrderTest.h"
+
+#include "src/math/totalorderf16.h"
+
+LIST_TOTALORDER_TESTS(float16, LIBC_NAMESPACE::totalorderf16)
diff --git a/libc/test/src/math/smoke/totalordermagf16_test.cpp b/libc/test/src/math/smoke/totalordermagf16_test.cpp
new file mode 100644
index 0000000000000..b09eb11cd9c3b
--- /dev/null
+++ b/libc/test/src/math/smoke/totalordermagf16_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for totalordermagf16 ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TotalOrderMagTest.h"
+
+#include "src/math/totalordermagf16.h"
+
+LIST_TOTALORDERMAG_TESTS(float16, LIBC_NAMESPACE::totalordermagf16)
More information about the libc-commits
mailing list