[libc-commits] [libc] [libc][math][c23] Add {totalorder, totalordermag}f16 C23 math functions (PR #95014)

via libc-commits libc-commits at lists.llvm.org
Mon Jun 10 10:35:13 PDT 2024


https://github.com/overmighty created https://github.com/llvm/llvm-project/pull/95014

None

>From 6b214b532824f6819cc50bbb9ebdf2de5e06cefb Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Mon, 10 Jun 2024 18:38:16 +0200
Subject: [PATCH 1/3] [libc][math][c23] Add totalorderf16 C23 math function

---
 libc/config/linux/aarch64/entrypoints.txt     |   1 +
 libc/config/linux/x86_64/entrypoints.txt      |   1 +
 libc/docs/c23.rst                             |   2 +-
 libc/docs/math/index.rst                      |   2 +
 libc/spec/stdc.td                             |   2 +
 libc/src/__support/FPUtil/BasicOperations.h   |  43 ++++++
 libc/src/__support/FPUtil/FPBits.h            |   4 +
 libc/src/math/CMakeLists.txt                  |   2 +
 libc/src/math/generic/CMakeLists.txt          |  12 ++
 libc/src/math/generic/totalorderf16.cpp       |  19 +++
 libc/src/math/totalorderf16.h                 |  20 +++
 libc/test/src/math/smoke/CMakeLists.txt       |  12 ++
 libc/test/src/math/smoke/TotalOrderTest.h     | 137 ++++++++++++++++++
 .../src/math/smoke/totalorderf16_test.cpp     |  13 ++
 14 files changed, 269 insertions(+), 1 deletion(-)
 create mode 100644 libc/src/math/generic/totalorderf16.cpp
 create mode 100644 libc/src/math/totalorderf16.h
 create mode 100644 libc/test/src/math/smoke/TotalOrderTest.h
 create mode 100644 libc/test/src/math/smoke/totalorderf16_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 8863749e12c6d..8206cc18284c0 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -539,6 +539,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.rintf16
     libc.src.math.roundf16
     libc.src.math.roundevenf16
+    libc.src.math.totalorderf16
     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 31ad0bc412836..84751c7779cb9 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -569,6 +569,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.rintf16
     libc.src.math.roundf16
     libc.src.math.roundevenf16
+    libc.src.math.totalorderf16
     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..a771f4feab3c2 100644
--- a/libc/docs/c23.rst
+++ b/libc/docs/c23.rst
@@ -42,7 +42,7 @@ Additions:
   * rsqrt*
   * __STDC_IEC_60559_DFP__ functions (_Decimal32, _Decimal64, _Decimal128)
   * compoundn*
-  * totalorder*
+  * totalorder* |check|
   * totalordermag*
   * getpayload*
   * setpayload*
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index 3e122fb8bc26e..727919d9e4a9e 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -210,6 +210,8 @@ Basic Operations
 +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | scalbn           | |check|          | |check|         | |check|                |                      | |check|                | 7.12.6.19              | F.10.3.19                  |
 +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| totalorder       |                  |                 |                        | |check|              |                        | F.10.12.1              | 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 b5b6dbc481bd7..be97a0a0c9343 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -708,6 +708,8 @@ 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">,
       ]
   >;
 
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index e5ac101fedc0e..cb669b0009265 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -240,6 +240,49 @@ 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(const T *x, const T *y) {
+  using FPBits = FPBits<T>;
+  FPBits xbits(*x);
+  FPBits ybits(*y);
+
+  if (LIBC_UNLIKELY(xbits.is_zero() && ybits.is_zero() || xbits.is_nan() ||
+                    ybits.is_nan())) {
+    // totalOrder(−0, +0) is true. totalOrder(+0, -0) is false.
+    if (xbits.is_zero() && ybits.is_zero()) {
+      Sign xsign = xbits.sign();
+      Sign ysign = ybits.sign();
+      return (xsign == Sign::NEG && ysign == Sign::POS) || xsign == ysign;
+    }
+
+    // totalOrder(−NaN, y) is true. totalOrder(+NaN, y) is false.
+    if (!ybits.is_nan())
+      return xbits.is_neg();
+    // totalOrder(x, +NaN) is true. totalOrder(x, -NaN) is false.
+    if (!xbits.is_nan())
+      return ybits.is_pos();
+
+    // Negative sign orders below positive sign.
+    if (xbits.is_neg() && ybits.is_pos())
+      return true;
+    if (xbits.is_pos() && ybits.is_neg())
+      return false;
+
+    // Signaling orders below quiet for +NaN, reverse for −NaN.
+    if (xbits.is_quiet_nan() && ybits.is_signaling_nan())
+      return xbits.is_neg();
+    if (xbits.is_signaling_nan() && ybits.is_quiet_nan())
+      return ybits.is_pos();
+
+    // Otherwise, the order of NaNs is implementation-defined (IEEE 754-2019).
+    // We order by payload.
+    return xbits.get_nan_payload() <= ybits.get_nan_payload();
+  }
+
+  return xbits.get_val() <= ybits.get_val();
+}
+
 } // namespace fputil
 } // namespace LIBC_NAMESPACE
 
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 559ecde767c30..f424e11ec9fd1 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -708,6 +708,10 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
   LIBC_INLINE constexpr void set_significand(StorageType sigVal) {
     bits = UP::merge(bits, sigVal, SIG_MASK);
   }
+
+  LIBC_INLINE constexpr StorageType get_nan_payload() const {
+    return bits & (FRACTION_MASK >> 1);
+  }
   // Unsafe function to create a floating point representation.
   // It simply packs the sign, biased exponent and mantissa values without
   // checking bound nor normalization.
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index f8582d8d42683..5d605fe8bbcb7 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -367,6 +367,8 @@ add_math_entrypoint_object(tanhf)
 add_math_entrypoint_object(tgamma)
 add_math_entrypoint_object(tgammaf)
 
+add_math_entrypoint_object(totalorderf16)
+
 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 caaa0ac23dc7a..4787ecfdf8565 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3551,3 +3551,15 @@ 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
+)
diff --git a/libc/src/math/generic/totalorderf16.cpp b/libc/src/math/generic/totalorderf16.cpp
new file mode 100644
index 0000000000000..b64f1eeaf3ddf
--- /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/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/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 84aa76c0a0881..d24e4076c0bed 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3509,3 +3509,15 @@ 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
+)
diff --git a/libc/test/src/math/smoke/TotalOrderTest.h b/libc/test/src/math/smoke/TotalOrderTest.h
new file mode 100644
index 0000000000000..9ed44b1b798d1
--- /dev/null
+++ b/libc/test/src/math/smoke/TotalOrderTest.h
@@ -0,0 +1,137 @@
+//===-- Utility class to test different 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, -aNaN, T(0.0)));
+    EXPECT_TRUE(funcWrapper(func, -aNaN, T(0.1)));
+    EXPECT_TRUE(funcWrapper(func, -aNaN, T(123.38)));
+
+    EXPECT_FALSE(funcWrapper(func, T(0.0), -aNaN));
+    EXPECT_FALSE(funcWrapper(func, T(0.1), -aNaN));
+    EXPECT_FALSE(funcWrapper(func, T(123.38), -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, -aNaN, aNaN));
+    EXPECT_TRUE(funcWrapper(func, -aNaN, sNaN));
+    EXPECT_TRUE(funcWrapper(func, -sNaN, aNaN));
+    EXPECT_TRUE(funcWrapper(func, -sNaN, sNaN));
+
+    EXPECT_FALSE(funcWrapper(func, aNaN, -aNaN));
+    EXPECT_FALSE(funcWrapper(func, aNaN, -sNaN));
+    EXPECT_FALSE(funcWrapper(func, sNaN, -aNaN));
+    EXPECT_FALSE(funcWrapper(func, sNaN, -sNaN));
+  }
+
+  void testQuietVsSignalingNaN(TotalOrderFunc func) {
+    EXPECT_TRUE(funcWrapper(func, -aNaN, -sNaN));
+    EXPECT_FALSE(funcWrapper(func, -sNaN, -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 snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val();
+
+    EXPECT_TRUE(funcWrapper(func, aNaN, aNaN));
+    EXPECT_TRUE(funcWrapper(func, -aNaN, -aNaN));
+    EXPECT_TRUE(funcWrapper(func, sNaN, sNaN));
+    EXPECT_TRUE(funcWrapper(func, -sNaN, -sNaN));
+
+    EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123));
+    EXPECT_TRUE(funcWrapper(func, -aNaN, -qnan_123));
+    EXPECT_TRUE(funcWrapper(func, sNaN, snan_123));
+    EXPECT_TRUE(funcWrapper(func, -sNaN, -snan_123));
+
+    EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN));
+    EXPECT_FALSE(funcWrapper(func, -qnan_123, -aNaN));
+    EXPECT_FALSE(funcWrapper(func, snan_123, sNaN));
+    EXPECT_FALSE(funcWrapper(func, -snan_123, -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)

>From 5c725f51fe9123bf686e79368384cfc1e687394e Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Mon, 10 Jun 2024 19:21:48 +0200
Subject: [PATCH 2/3] [libc][math][c23] Add totalordermagf16 C23 math function

---
 libc/config/linux/aarch64/entrypoints.txt     |   1 +
 libc/config/linux/x86_64/entrypoints.txt      |   1 +
 libc/docs/c23.rst                             |   2 +-
 libc/docs/math/index.rst                      |   2 +
 libc/spec/stdc.td                             |   2 +
 libc/src/__support/FPUtil/BasicOperations.h   |   8 +
 libc/src/math/CMakeLists.txt                  |   2 +
 libc/src/math/generic/CMakeLists.txt          |  12 ++
 libc/src/math/generic/totalordermagf16.cpp    |  20 +++
 libc/src/math/totalordermagf16.h              |  20 +++
 libc/test/UnitTest/FPMatcher.h                |   6 +-
 libc/test/src/math/smoke/CMakeLists.txt       |  12 ++
 libc/test/src/math/smoke/TotalOrderMagTest.h  | 143 ++++++++++++++++++
 .../src/math/smoke/totalordermagf16_test.cpp  |  13 ++
 14 files changed, 241 insertions(+), 3 deletions(-)
 create mode 100644 libc/src/math/generic/totalordermagf16.cpp
 create mode 100644 libc/src/math/totalordermagf16.h
 create mode 100644 libc/test/src/math/smoke/TotalOrderMagTest.h
 create mode 100644 libc/test/src/math/smoke/totalordermagf16_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 8206cc18284c0..dba4835afb745 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -540,6 +540,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     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 84751c7779cb9..90505738d624d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -570,6 +570,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     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 a771f4feab3c2..4134befd1ed35 100644
--- a/libc/docs/c23.rst
+++ b/libc/docs/c23.rst
@@ -43,7 +43,7 @@ Additions:
   * __STDC_IEC_60559_DFP__ functions (_Decimal32, _Decimal64, _Decimal128)
   * compoundn*
   * totalorder* |check|
-  * totalordermag*
+  * totalordermag* |check|
   * getpayload*
   * setpayload*
   * iscannonical
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index 727919d9e4a9e..953bdd8b642ad 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -212,6 +212,8 @@ Basic Operations
 +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | 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 be97a0a0c9343..b1b02a8e1ed31 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -710,6 +710,8 @@ def StdC : StandardSpec<"stdc"> {
           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 cb669b0009265..168b3d308f0ee 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -283,6 +283,14 @@ totalorder(const T *x, const T *y) {
   return xbits.get_val() <= ybits.get_val();
 }
 
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+totalordermag(const T *x, const T *y) {
+  T abs_x = abs(*x);
+  T abs_y = abs(*y);
+  return totalorder(&abs_x, &abs_y);
+}
+
 } // namespace fputil
 } // namespace LIBC_NAMESPACE
 
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 5d605fe8bbcb7..3c1a5c86f6b48 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -369,6 +369,8 @@ 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 4787ecfdf8565..a13cadc8acd0c 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3563,3 +3563,15 @@ add_entrypoint_object(
   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/totalordermagf16.cpp b/libc/src/math/generic/totalordermagf16.cpp
new file mode 100644
index 0000000000000..868e155bac32b
--- /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/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 d24e4076c0bed..706e23518ed58 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3521,3 +3521,15 @@ add_fp_unittest(
   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..013a7fc92f9b1
--- /dev/null
+++ b/libc/test/src/math/smoke/TotalOrderMagTest.h
@@ -0,0 +1,143 @@
+//===-- 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, neg_aNaN, neg_aNaN));
+    EXPECT_TRUE(funcWrapper(func, sNaN, sNaN));
+    EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN));
+
+    EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123));
+    EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_qnan_123));
+    EXPECT_TRUE(funcWrapper(func, sNaN, snan_123));
+    EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_snan_123));
+
+    EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN));
+    EXPECT_FALSE(funcWrapper(func, neg_qnan_123, neg_aNaN));
+    EXPECT_FALSE(funcWrapper(func, snan_123, sNaN));
+    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/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)

>From e295094e321675303a231b818fac67e4b6617455 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Mon, 10 Jun 2024 19:26:02 +0200
Subject: [PATCH 3/3] [libc][math][c23] Fix NaN negation in TotalOrderTest.h

---
 libc/test/src/math/smoke/TotalOrderTest.h | 48 ++++++++++++-----------
 1 file changed, 25 insertions(+), 23 deletions(-)

diff --git a/libc/test/src/math/smoke/TotalOrderTest.h b/libc/test/src/math/smoke/TotalOrderTest.h
index 9ed44b1b798d1..c6939e6a3eaac 100644
--- a/libc/test/src/math/smoke/TotalOrderTest.h
+++ b/libc/test/src/math/smoke/TotalOrderTest.h
@@ -65,13 +65,13 @@ class TotalOrderTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   }
 
   void testSingleNaN(TotalOrderFunc func) {
-    EXPECT_TRUE(funcWrapper(func, -aNaN, T(0.0)));
-    EXPECT_TRUE(funcWrapper(func, -aNaN, T(0.1)));
-    EXPECT_TRUE(funcWrapper(func, -aNaN, T(123.38)));
+    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), -aNaN));
-    EXPECT_FALSE(funcWrapper(func, T(0.1), -aNaN));
-    EXPECT_FALSE(funcWrapper(func, T(123.38), -aNaN));
+    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));
@@ -83,42 +83,44 @@ class TotalOrderTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   }
 
   void testNaNSigns(TotalOrderFunc func) {
-    EXPECT_TRUE(funcWrapper(func, -aNaN, aNaN));
-    EXPECT_TRUE(funcWrapper(func, -aNaN, sNaN));
-    EXPECT_TRUE(funcWrapper(func, -sNaN, aNaN));
-    EXPECT_TRUE(funcWrapper(func, -sNaN, sNaN));
-
-    EXPECT_FALSE(funcWrapper(func, aNaN, -aNaN));
-    EXPECT_FALSE(funcWrapper(func, aNaN, -sNaN));
-    EXPECT_FALSE(funcWrapper(func, sNaN, -aNaN));
-    EXPECT_FALSE(funcWrapper(func, sNaN, -sNaN));
+    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, -aNaN, -sNaN));
-    EXPECT_FALSE(funcWrapper(func, -sNaN, -aNaN));
+    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, -aNaN, -aNaN));
+    EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_aNaN));
     EXPECT_TRUE(funcWrapper(func, sNaN, sNaN));
-    EXPECT_TRUE(funcWrapper(func, -sNaN, -sNaN));
+    EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN));
 
     EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123));
-    EXPECT_TRUE(funcWrapper(func, -aNaN, -qnan_123));
+    EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_qnan_123));
     EXPECT_TRUE(funcWrapper(func, sNaN, snan_123));
-    EXPECT_TRUE(funcWrapper(func, -sNaN, -snan_123));
+    EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_snan_123));
 
     EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN));
-    EXPECT_FALSE(funcWrapper(func, -qnan_123, -aNaN));
+    EXPECT_FALSE(funcWrapper(func, neg_qnan_123, neg_aNaN));
     EXPECT_FALSE(funcWrapper(func, snan_123, sNaN));
-    EXPECT_FALSE(funcWrapper(func, -snan_123, -sNaN));
+    EXPECT_FALSE(funcWrapper(func, neg_snan_123, neg_sNaN));
   }
 };
 



More information about the libc-commits mailing list