[libcxx-commits] [libcxx] [libc++][math] Add `constexpr` to comparison functions (PR #210075)

Lucas Mellone via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 23 05:32:53 PDT 2026


https://github.com/lknknm updated https://github.com/llvm/llvm-project/pull/210075

>From 1fc2d6029a58ceaed872953980ae0f9b2bc9e178 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 16:47:35 +0200
Subject: [PATCH 01/25] add: constexpr to isgreater

---
 libcxx/include/__math/traits.h                        | 11 +++++------
 .../numerics/c.math/constexpr-cxx23-clang.pass.cpp    |  6 +++---
 .../numerics/c.math/constexpr-cxx23-gcc.pass.cpp      |  6 +++---
 3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index ff22cee7305d7..28269eef46743 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -82,8 +82,7 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool
-    isinf(double __x) _NOEXCEPT {
+    bool isinf(double __x) _NOEXCEPT {
   return __builtin_isinf(__x);
 }
 
@@ -106,8 +105,7 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool
-    isnan(double __x) _NOEXCEPT {
+    bool isnan(double __x) _NOEXCEPT {
   return __builtin_isnan(__x);
 }
 
@@ -137,7 +135,8 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 // isgreater
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
+isgreater(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreater((type)__x, (type)__y);
 }
@@ -216,7 +215,7 @@ template <class _A1>
 
 template <class _A1, class _A2>
   requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
-[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) noexcept {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreater((type)__x, (type)__y);
 }
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
index 93865afc5e68b..642806ffbd960 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
@@ -227,9 +227,9 @@ int main(int, char**) {
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 0);
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
index d8779706bcee2..34513b459a056 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
@@ -221,9 +221,9 @@ int main(int, char**) {
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
   ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
   ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 0);

>From f6f5b24db9910930a4f63731ebc408653c43b530 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 16:51:44 +0200
Subject: [PATCH 02/25] revert: clang-format mistake

---
 libcxx/include/__math/traits.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 28269eef46743..48a68f31c2101 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -82,7 +82,8 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool isinf(double __x) _NOEXCEPT {
+    bool
+    isinf(double __x) _NOEXCEPT {
   return __builtin_isinf(__x);
 }
 
@@ -105,7 +106,8 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool isnan(double __x) _NOEXCEPT {
+    bool
+    isnan(double __x) _NOEXCEPT {
   return __builtin_isnan(__x);
 }
 

>From 9cfce54da2a26d9654a04d41c577bd5dacabe942 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 23:44:41 +0200
Subject: [PATCH 03/25] add: isgreater.pass.cpp

---
 .../std/numerics/c.math/isgreater.pass.cpp    | 71 +++++++++++++++++++
 1 file changed, 71 insertions(+)
 create mode 100644 libcxx/test/std/numerics/c.math/isgreater.pass.cpp

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
new file mode 100644
index 0000000000000..7b119df05f791
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// bool isgreater(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
+template <typename T>
+struct ZeroConvertibleTo {
+  operator T() const { return T(0); }
+};
+
+int main(int, char**) {
+  types::for_each(types::floating_point_types(), TestFloat());
+  types::for_each(types::integral_types(), TestInt());
+
+  return 0;
+}

>From 184002328c9527189365872f28e6e5b7d1548ed6 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 16 Jul 2026 23:53:01 +0200
Subject: [PATCH 04/25] add: mixed-type promotion tests

---
 .../test/std/numerics/c.math/isgreater.pass.cpp | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 7b119df05f791..780b61e321cf1 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -23,6 +23,8 @@ struct TestFloat {
   template <class T>
   static TEST_CONSTEXPR_CXX23 bool test() {
     assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
+    assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
 
     return true;
   }
@@ -40,6 +42,8 @@ struct TestInt {
   template <class T>
   static TEST_CONSTEXPR_CXX23 bool test() {
     assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
+    assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
 
     return true;
   }
@@ -58,14 +62,17 @@ struct ConvertibleTo {
   operator T() const { return T(1); }
 };
 
-template <typename T>
-struct ZeroConvertibleTo {
-  operator T() const { return T(0); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
 
+  // Make sure we can call `std::isgreater` with mixed-type promotions with __promote_t<_A1, _A2>.
+  {
+    assert(std::isgreater(2.0, 1));     // double vs int
+    assert(!std::isgreater(1, 2.0f));   // int vs float
+    assert(std::isgreater(2.0L, 1.0f)); // long double vs float
+    assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
+  }
+
   return 0;
 }

>From 3dd1d455e2ef97c5ba3ec364627d4a4479d6deab Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 00:01:01 +0200
Subject: [PATCH 05/25] add: infinity and NaN assertion tests

---
 libcxx/test/std/numerics/c.math/isgreater.pass.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 780b61e321cf1..608c044d49ff4 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -26,6 +26,15 @@ struct TestFloat {
     assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
     assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
 
+    assert(std::isgreater(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::max()));
+    assert(!std::isgreater(-std::numeric_limits<T>::infinity(), std::numeric_limits<T>::lowest()));
+    assert(!std::isgreater(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()));
+
+    assert(!std::isgreater(std::numeric_limits<T>::quiet_NaN(), T(0)));
+    assert(!std::isgreater(T(0), std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::isgreater(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::isgreater(std::numeric_limits<T>::signaling_NaN(), T(0)));
+
     return true;
   }
 

>From 4e3a4fe538be67ade2045e862539a6765fb91d77 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 00:03:02 +0200
Subject: [PATCH 06/25] add: signed int tests

---
 libcxx/test/std/numerics/c.math/isgreater.pass.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 608c044d49ff4..07f26847fb1c9 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -54,6 +54,11 @@ struct TestInt {
     assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
     assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
 
+    if (std::is_signed<T>::value) {
+      assert(std::isgreater(T(-1), std::numeric_limits<T>::lowest()));
+      assert(!std::isgreater(std::numeric_limits<T>::lowest(), T(-1)));
+    }
+
     return true;
   }
 

>From 207837d2233abd69599e9e45d02059b46bdddc91 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 00:18:21 +0200
Subject: [PATCH 07/25] add: lowest int comparisons

---
 libcxx/test/std/numerics/c.math/isgreater.pass.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 07f26847fb1c9..c7853974d7a66 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -54,6 +54,9 @@ struct TestInt {
     assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
     assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
 
+    assert(!std::isgreater(T(1), T(1)));
+    assert(!std::isgreater(std::numeric_limits<T>::lowest(), T(0)));
+
     if (std::is_signed<T>::value) {
       assert(std::isgreater(T(-1), std::numeric_limits<T>::lowest()));
       assert(!std::isgreater(std::numeric_limits<T>::lowest(), T(-1)));

>From 7afee657c477977b070c404c8288823e6015e045 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 14:40:56 +0200
Subject: [PATCH 08/25] apply: constexpr to all is<...> math functions and flip
 tests

---
 libcxx/include/__math/traits.h                | 20 ++++++-------
 .../c.math/constexpr-cxx23-clang.pass.cpp     | 30 +++++++++----------
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 48a68f31c2101..7c0fdc90ce031 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -146,7 +146,7 @@ isgreater(_A1 __x, _A2 __y) _NOEXCEPT {
 // isgreaterequal
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreaterequal((type)__x, (type)__y);
 }
@@ -154,7 +154,7 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
 // isless
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isless((type)__x, (type)__y);
 }
@@ -162,7 +162,7 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
 // islessequal
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_islessequal((type)__x, (type)__y);
 }
@@ -170,7 +170,7 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
 // islessgreater
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_islessgreater((type)__x, (type)__y);
 }
@@ -178,7 +178,7 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
 // isunordered
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isunordered((type)__x, (type)__y);
 }
@@ -224,35 +224,35 @@ template <class _A1, class _A2>
 
 template <class _A1, class _A2>
   requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
-[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) noexcept {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreaterequal((type)__x, (type)__y);
 }
 
 template <class _A1, class _A2>
   requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
-[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) noexcept {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isless((type)__x, (type)__y);
 }
 
 template <class _A1, class _A2>
   requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
-[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) noexcept {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_islessequal((type)__x, (type)__y);
 }
 
 template <class _A1, class _A2>
   requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
-[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) noexcept {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_islessgreater((type)__x, (type)__y);
 }
 
 template <class _A1, class _A2>
   requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
-[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) noexcept {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isunordered((type)__x, (type)__y);
 }
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
index 642806ffbd960..e8211ebe94230 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
@@ -231,25 +231,25 @@ int main(int, char**) {
   ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
   ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0L, 0.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isless(-1.0f, 0.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isless(-1.0, 0.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isless(-1.0L, 0.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isless(-1.0f, 0.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isless(-1.0, 0.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isless(-1.0L, 0.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessequal(-1.0f, 0.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessequal(-1.0, 0.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessequal(-1.0L, 0.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessequal(-1.0f, 0.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessequal(-1.0, 0.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessequal(-1.0L, 0.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessgreater(-1.0f, 0.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessgreater(-1.0, 0.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessgreater(-1.0L, 0.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessgreater(-1.0f, 0.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessgreater(-1.0, 0.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessgreater(-1.0L, 0.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isunordered(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isunordered(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isunordered(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isunordered(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isunordered(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isunordered(-1.0L, 0.0L) == 0);
 
   assert(!ImplementedP0533R9 && R"(
 Congratulations! You just have implemented P0533R9 (https://wg21.link/p0533r9).

>From ebb642255cc08a2940459b58aa72b432c7b77748 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 15:16:18 +0200
Subject: [PATCH 09/25] fix: formatting

---
 libcxx/include/__math/traits.h | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 7c0fdc90ce031..0d6afca2e8936 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -82,9 +82,7 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool
-    isinf(double __x) _NOEXCEPT {
-  return __builtin_isinf(__x);
+    bool turn __builtin_isinf(__x);
 }
 
 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT {
@@ -106,10 +104,8 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool
-    isnan(double __x) _NOEXCEPT {
-  return __builtin_isnan(__x);
-}
+    bool isnan(double __x) _NOEXCEPT {
+  return 
 
 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT {
   return __builtin_isnan(__x);
@@ -146,7 +142,8 @@ isgreater(_A1 __x, _A2 __y) _NOEXCEPT {
 // isgreaterequal
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
+isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreaterequal((type)__x, (type)__y);
 }
@@ -156,13 +153,13 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
-  return __builtin_isless((type)__x, (type)__y);
-}
+  return __builtin_isless((type)__x, (type)__y); }
 
 // islessequal
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
+islessequal(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_islessequal((type)__x, (type)__y);
 }
@@ -170,7 +167,8 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
 // islessgreater
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
+islessgreater(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_islessgreater((type)__x, (type)__y);
 }
@@ -178,7 +176,8 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
 // isunordered
 
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
+isunordered(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isunordered((type)__x, (type)__y);
 }
@@ -224,7 +223,8 @@ template <class _A1, class _A2>
 
 template <class _A1, class _A2>
   requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>
-[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) noexcept {
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool
+isgreaterequal(_A1 __x, _A2 __y) noexcept {
   using type = __promote_t<_A1, _A2>;
   return __builtin_isgreaterequal((type)__x, (type)__y);
 }

>From 336fa94a06ee606f43a03fcbed9c2b8faeaeab04 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 15:20:04 +0200
Subject: [PATCH 10/25] fix: accidental automatic formatting (clang-format)

---
 libcxx/include/__math/traits.h | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 0d6afca2e8936..ef20e330df35c 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -82,7 +82,9 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool turn __builtin_isinf(__x);
+    bool
+    isinf(double __x) _NOEXCEPT {
+  return __builtin_isinf(__x);
 }
 
 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT {
@@ -104,8 +106,10 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 #ifdef _LIBCPP_PREFERRED_OVERLOAD
 _LIBCPP_PREFERRED_OVERLOAD
 #endif
-    bool isnan(double __x) _NOEXCEPT {
-  return 
+    bool
+    isnan(double __x) _NOEXCEPT {
+  return __builtin_isnan(__x);
+}
 
 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT {
   return __builtin_isnan(__x);

>From 84b6b7442b8e8f0f0cf1672557a6e8b3abca0d7b Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 15:37:39 +0200
Subject: [PATCH 11/25] formatter: remove accidental trailing space

---
 libcxx/include/__math/traits.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index ef20e330df35c..f32dc47ab1b1b 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -157,7 +157,8 @@ isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT {
 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT {
   using type = __promote_t<_A1, _A2>;
-  return __builtin_isless((type)__x, (type)__y); }
+  return __builtin_isless((type)__x, (type)__y);
+}
 
 // islessequal
 

>From 9f279ea0daa21db0954068d8a4a68080f4c5e767 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 16:48:11 +0200
Subject: [PATCH 12/25] add: isgreaterequal.pass.cpp

---
 .../numerics/c.math/isgreaterequal.pass.cpp   | 93 +++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp

diff --git a/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
new file mode 100644
index 0000000000000..d6ae553e961e5
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// bool isgreaterequalequal(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isgreaterequal(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::isgreaterequal(T(0), std::numeric_limits<T>::max()));
+    assert(std::isgreaterequal(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+
+    assert(std::isgreaterequal(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::max()));
+    assert(!std::isgreaterequal(-std::numeric_limits<T>::infinity(), std::numeric_limits<T>::lowest()));
+    assert(std::isgreaterequal(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()));
+
+    assert(!std::isgreaterequal(std::numeric_limits<T>::quiet_NaN(), T(0)));
+    assert(!std::isgreaterequal(T(0), std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::isgreaterequal(std::numeric_limits<T>::signaling_NaN(), T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isgreaterequal(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::isgreaterequal(T(0), std::numeric_limits<T>::max()));
+    assert(std::isgreaterequal(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+
+    assert(std::isgreaterequal(T(1), T(1)));
+
+    if (std::is_signed<T>::value) {
+      assert(std::isgreaterequal(T(-1), std::numeric_limits<T>::lowest()));
+      assert(!std::isgreaterequal(std::numeric_limits<T>::lowest(), T(-1)));
+    }
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
+int main(int, char**) {
+  types::for_each(types::floating_point_types(), TestFloat());
+  types::for_each(types::integral_types(), TestInt());
+
+  // Make sure we can call `std::isgreaterequal` with mixed-type promotions with __promote_t<_A1, _A2>.
+  {
+    assert(std::isgreaterequal(2.0, 1));     // double vs int
+    assert(!std::isgreaterequal(1, 2.0f));   // int vs float
+    assert(std::isgreaterequal(2.0L, 1.0f)); // long double vs float
+    assert(!std::isgreaterequal(std::numeric_limits<double>::quiet_NaN(), 0));
+  }
+
+  return 0;
+}

>From 8a651d6936cf81f5ca167d67b0a28280ceec4116 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 23:04:03 +0200
Subject: [PATCH 13/25] initial: add isless.pass.cpp

---
 .../test/std/numerics/c.math/isless.pass.cpp  | 88 +++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 libcxx/test/std/numerics/c.math/isless.pass.cpp

diff --git a/libcxx/test/std/numerics/c.math/isless.pass.cpp b/libcxx/test/std/numerics/c.math/isless.pass.cpp
new file mode 100644
index 0000000000000..1b9c1aacd0d13
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isless.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// bool isless(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isless(std::numeric_limits<T>::max(), T(0)));
+    assert(std::isless(T(0), std::numeric_limits<T>::max()));
+
+    assert(!std::isless(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::max()));
+    assert(std::isless(-std::numeric_limits<T>::infinity(), std::numeric_limits<T>::lowest()));
+
+    assert(!std::isless(T(0), std::numeric_limits<T>::quiet_NaN()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isless(std::numeric_limits<T>::max(), T(0)));
+    assert(std::isless(T(0), std::numeric_limits<T>::max()));
+    assert(!std::isless(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+
+    assert(!std::isless(T(1), T(1)));
+
+    if (std::is_signed<T>::value) {
+      assert(!std::isless(T(-1), std::numeric_limits<T>::lowest()));
+      assert(std::isless(std::numeric_limits<T>::lowest(), T(-1)));
+    }
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
+int main(int, char**) {
+  types::for_each(types::floating_point_types(), TestFloat());
+  types::for_each(types::integral_types(), TestInt());
+
+  // Make sure we can call `std::isless` with mixed-type promotions with __promote_t<_A1, _A2>.
+  {
+    assert(!std::isless(2.0, 1));     // double vs int
+    assert(std::isless(1, 2.0f));   // int vs float
+    assert(!std::isless(2.0L, 1.0f)); // long double vs float
+  }
+
+  return 0;
+}

>From 67d88113e5987460d20b2a0001e6aab7e53a57d5 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 17 Jul 2026 23:57:29 +0200
Subject: [PATCH 14/25] add: islessequal.pass.cpp

---
 .../std/numerics/c.math/islessequal.pass.cpp  | 92 +++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 libcxx/test/std/numerics/c.math/islessequal.pass.cpp

diff --git a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
new file mode 100644
index 0000000000000..98fb3a9e7770a
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
@@ -0,0 +1,92 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// bool islessequalequal(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::islessequal(std::numeric_limits<T>::max(), T(0)));
+    assert(std::islessequal(T(0), std::numeric_limits<T>::max()));
+    assert(std::islessequal(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+
+    assert(!std::islessequal(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::max()));
+    assert(std::islessequal(-std::numeric_limits<T>::infinity(), std::numeric_limits<T>::lowest()));
+    assert(std::islessequal(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()));
+
+    assert(!std::islessequal(std::numeric_limits<T>::quiet_NaN(), T(0)));
+    assert(!std::islessequal(T(0), std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::islessequal(std::numeric_limits<T>::signaling_NaN(), T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::islessequal(std::numeric_limits<T>::max(), T(0)));
+    assert(std::islessequal(T(0), std::numeric_limits<T>::max()));
+    assert(std::islessequal(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+
+    assert(std::islessequal(T(1), T(1)));
+
+    if (std::is_signed<T>::value) {
+      assert(!std::islessequal(T(-1), std::numeric_limits<T>::lowest()));
+      assert(std::islessequal(std::numeric_limits<T>::lowest(), T(-1)));
+    }
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
+int main(int, char**) {
+  types::for_each(types::floating_point_types(), TestFloat());
+  types::for_each(types::integral_types(), TestInt());
+
+  // Make sure we can call `std::islessequal` with mixed-type promotions with __promote_t<_A1, _A2>.
+  {
+    assert(!std::islessequal(2.0, 1));     // double vs int
+    assert(std::islessequal(1, 2.0f));   // int vs float
+    assert(!std::islessequal(2.0L, 1.0f)); // long double vs float
+  }
+
+  return 0;
+}

>From 6d1e2ff8878af3188e953f68bb199406ff942354 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 18 Jul 2026 00:00:33 +0200
Subject: [PATCH 15/25] fix: clang-format

---
 libcxx/test/std/numerics/c.math/isless.pass.cpp      | 2 +-
 libcxx/test/std/numerics/c.math/islessequal.pass.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isless.pass.cpp b/libcxx/test/std/numerics/c.math/isless.pass.cpp
index 1b9c1aacd0d13..af999db6166b3 100644
--- a/libcxx/test/std/numerics/c.math/isless.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isless.pass.cpp
@@ -80,7 +80,7 @@ int main(int, char**) {
   // Make sure we can call `std::isless` with mixed-type promotions with __promote_t<_A1, _A2>.
   {
     assert(!std::isless(2.0, 1));     // double vs int
-    assert(std::isless(1, 2.0f));   // int vs float
+    assert(std::isless(1, 2.0f));     // int vs float
     assert(!std::isless(2.0L, 1.0f)); // long double vs float
   }
 
diff --git a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
index 98fb3a9e7770a..2023b062f55f9 100644
--- a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
@@ -84,7 +84,7 @@ int main(int, char**) {
   // Make sure we can call `std::islessequal` with mixed-type promotions with __promote_t<_A1, _A2>.
   {
     assert(!std::islessequal(2.0, 1));     // double vs int
-    assert(std::islessequal(1, 2.0f));   // int vs float
+    assert(std::islessequal(1, 2.0f));     // int vs float
     assert(!std::islessequal(2.0L, 1.0f)); // long double vs float
   }
 

>From 71b5f4cf216bba7e770e854906b5112d93cbe367 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 18 Jul 2026 01:57:12 +0200
Subject: [PATCH 16/25] add: islessgreater.pass.cpp and isunordered.pass.cpp

---
 .../std/numerics/c.math/islessequal.pass.cpp  |  2 +-
 .../numerics/c.math/islessgreater.pass.cpp    | 91 +++++++++++++++++++
 .../std/numerics/c.math/isunordered.pass.cpp  | 78 ++++++++++++++++
 3 files changed, 170 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
 create mode 100644 libcxx/test/std/numerics/c.math/isunordered.pass.cpp

diff --git a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
index 2023b062f55f9..2b0be4ff37035 100644
--- a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// bool islessequalequal(floating-point-type x, floating-point-type y); // constexpr since C++23
+// bool islessequal(floating-point-type x, floating-point-type y); // constexpr since C++23
 
 // We don't control the implementation on windows
 // UNSUPPORTED: windows
diff --git a/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp b/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
new file mode 100644
index 0000000000000..40fbb7f4a4e41
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// bool islessgreater(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::islessgreater(T(1), T(2)));
+    assert(std::islessgreater(T(2), T(1)));
+    assert(!std::islessgreater(T(1), T(1)));
+
+    assert(!std::islessgreater(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()));
+    assert(std::islessgreater(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::max()));
+
+    assert(!std::islessgreater(std::numeric_limits<T>::quiet_NaN(), T(0)));
+    assert(!std::islessgreater(T(0), std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::islessgreater(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    if (!std::is_same<T, bool>::value) {
+      assert(std::islessgreater(T(1), T(2)));
+      assert(std::islessgreater(T(2), T(1)));
+    }
+
+    assert(!std::islessgreater(T(1), T(1)));
+
+    assert(!std::islessgreater(T(1), T(1)));
+    assert(std::islessgreater(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::islessgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+
+    if (std::is_signed<T>::value) {
+      assert(std::islessgreater(T(-1), T(1)));
+      assert(std::islessgreater(std::numeric_limits<T>::lowest(), T(0)));
+      assert(std::islessgreater(T(0), std::numeric_limits<T>::lowest()));
+      assert(!std::islessgreater(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest()));
+    }
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
+int main(int, char**) {
+  types::for_each(types::floating_point_types(), TestFloat());
+  types::for_each(types::integral_types(), TestInt());
+
+  return 0;
+}
diff --git a/libcxx/test/std/numerics/c.math/isunordered.pass.cpp b/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
new file mode 100644
index 0000000000000..ed7740d195163
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// bool isunordered(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isunordered(T(1), T(2)));
+    assert(!std::isunordered(T(1), T(1)));
+
+    assert(std::isunordered(std::numeric_limits<T>::quiet_NaN(), T(0)));
+    assert(std::isunordered(T(0), std::numeric_limits<T>::quiet_NaN()));
+    assert(std::isunordered(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()));
+
+    assert(std::isunordered(std::numeric_limits<T>::signaling_NaN(), T(0)));
+    assert(!std::isunordered(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()));
+    assert(!std::isunordered(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isunordered(T(1), T(2)));
+    assert(!std::isunordered(T(1), T(1)));
+    assert(!std::isunordered(std::numeric_limits<T>::max(), T(0)));
+    assert(!std::isunordered(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
+int main(int, char**) {
+  types::for_each(types::floating_point_types(), TestFloat());
+  types::for_each(types::integral_types(), TestInt());
+
+  return 0;
+}

>From ef949295028c1bd5d6a19881e122393aada59194 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 18 Jul 2026 02:01:27 +0200
Subject: [PATCH 17/25] flip assert tests for gcc

---
 .../c.math/constexpr-cxx23-gcc.pass.cpp       | 30 +++++++++----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
index 34513b459a056..8d814e81f8bc6 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
@@ -225,25 +225,25 @@ int main(int, char**) {
   ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
   ASSERT_CONSTEXPR_CXX23(std::isgreater(-1.0L, 0.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isgreaterequal(-1.0L, 0.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isless(-1.0f, 0.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isless(-1.0, 0.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isless(-1.0L, 0.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isless(-1.0f, 0.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isless(-1.0, 0.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isless(-1.0L, 0.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessequal(-1.0f, 0.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessequal(-1.0, 0.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessequal(-1.0L, 0.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessequal(-1.0f, 0.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessequal(-1.0, 0.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessequal(-1.0L, 0.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessgreater(-1.0f, 0.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessgreater(-1.0, 0.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::islessgreater(-1.0L, 0.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessgreater(-1.0f, 0.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessgreater(-1.0, 0.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::islessgreater(-1.0L, 0.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isunordered(-1.0f, 0.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isunordered(-1.0, 0.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isunordered(-1.0L, 0.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isunordered(-1.0f, 0.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isunordered(-1.0, 0.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isunordered(-1.0L, 0.0L) == 0);
 
   assert(!ImplementedP0533R9 && R"(
 Congratulations! You just have implemented P0533R9 (https://wg21.link/p0533r9).

>From f6a4fa78d49d5bd14219d1cb7885d0d6bf4524ba Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 18 Jul 2026 02:02:43 +0200
Subject: [PATCH 18/25] fix typo in isgreaterequal.pass.cpp

---
 libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
index d6ae553e961e5..f2a4159882654 100644
--- a/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// bool isgreaterequalequal(floating-point-type x, floating-point-type y); // constexpr since C++23
+// bool isgreaterequal(floating-point-type x, floating-point-type y); // constexpr since C++23
 
 // We don't control the implementation on windows
 // UNSUPPORTED: windows

>From 62ae94cc86a2b43b61a9ba80eadfc4013bcced15 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 18 Jul 2026 18:18:09 +0200
Subject: [PATCH 19/25] update: cmath synopsis for is<...>

---
 libcxx/include/cmath | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 208791ca0804c..65bf07aed059b 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -140,17 +140,17 @@ bool signbit(arithmetic x);
 
 int fpclassify(arithmetic x);
 
-bool isfinite(arithmetic x);
-bool isinf(arithmetic x);
-bool isnan(arithmetic x);
-bool isnormal(arithmetic x);
-
-bool isgreater(arithmetic x, arithmetic y);
-bool isgreaterequal(arithmetic x, arithmetic y);
-bool isless(arithmetic x, arithmetic y);
-bool islessequal(arithmetic x, arithmetic y);
-bool islessgreater(arithmetic x, arithmetic y);
-bool isunordered(arithmetic x, arithmetic y);
+bool isfinite(arithmetic x); // constexpr since C++23
+bool isinf(arithmetic x);    // constexpr since C++23
+bool isnan(arithmetic x);    // constexpr since C++23
+bool isnormal(arithmetic x); // constexpr since C++23
+
+bool isgreater(arithmetic x, arithmetic y);      // constexpr since C++23
+bool isgreaterequal(arithmetic x, arithmetic y); // constexpr since C++23
+bool isless(arithmetic x, arithmetic y);         // constexpr since C++23
+bool islessequal(arithmetic x, arithmetic y);    // constexpr since C++23
+bool islessgreater(arithmetic x, arithmetic y);  // constexpr since C++23
+bool isunordered(arithmetic x, arithmetic y);    // constexpr since C++23
 
 floating_point acosh (arithmetic x);
 float          acoshf(float x);

>From 1a641131cba0843189ecd9364df414c8baa85cad Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Mon, 20 Jul 2026 12:31:47 +0200
Subject: [PATCH 20/25] remove: UNSUPPORTED windows from tests

---
 libcxx/test/std/numerics/c.math/isgreater.pass.cpp      | 3 ---
 libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp | 3 ---
 libcxx/test/std/numerics/c.math/isless.pass.cpp         | 3 ---
 libcxx/test/std/numerics/c.math/islessequal.pass.cpp    | 3 ---
 libcxx/test/std/numerics/c.math/islessgreater.pass.cpp  | 3 ---
 libcxx/test/std/numerics/c.math/isunordered.pass.cpp    | 3 ---
 6 files changed, 18 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index c7853974d7a66..269bb31e016cf 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -8,9 +8,6 @@
 
 // bool isgreater(floating-point-type x, floating-point-type y); // constexpr since C++23
 
-// We don't control the implementation on windows
-// UNSUPPORTED: windows
-
 #include <cassert>
 #include <cmath>
 #include <limits>
diff --git a/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
index f2a4159882654..27fa43812812a 100644
--- a/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
@@ -8,9 +8,6 @@
 
 // bool isgreaterequal(floating-point-type x, floating-point-type y); // constexpr since C++23
 
-// We don't control the implementation on windows
-// UNSUPPORTED: windows
-
 #include <cassert>
 #include <cmath>
 #include <limits>
diff --git a/libcxx/test/std/numerics/c.math/isless.pass.cpp b/libcxx/test/std/numerics/c.math/isless.pass.cpp
index af999db6166b3..cc68a49beead9 100644
--- a/libcxx/test/std/numerics/c.math/isless.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isless.pass.cpp
@@ -8,9 +8,6 @@
 
 // bool isless(floating-point-type x, floating-point-type y); // constexpr since C++23
 
-// We don't control the implementation on windows
-// UNSUPPORTED: windows
-
 #include <cassert>
 #include <cmath>
 #include <limits>
diff --git a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
index 2b0be4ff37035..5f58bbc993613 100644
--- a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
@@ -8,9 +8,6 @@
 
 // bool islessequal(floating-point-type x, floating-point-type y); // constexpr since C++23
 
-// We don't control the implementation on windows
-// UNSUPPORTED: windows
-
 #include <cassert>
 #include <cmath>
 #include <limits>
diff --git a/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp b/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
index 40fbb7f4a4e41..6a10708359bbe 100644
--- a/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
@@ -8,9 +8,6 @@
 
 // bool islessgreater(floating-point-type x, floating-point-type y); // constexpr since C++23
 
-// We don't control the implementation on windows
-// UNSUPPORTED: windows
-
 #include <cassert>
 #include <cmath>
 #include <limits>
diff --git a/libcxx/test/std/numerics/c.math/isunordered.pass.cpp b/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
index ed7740d195163..3f140106a423f 100644
--- a/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
@@ -8,9 +8,6 @@
 
 // bool isunordered(floating-point-type x, floating-point-type y); // constexpr since C++23
 
-// We don't control the implementation on windows
-// UNSUPPORTED: windows
-
 #include <cassert>
 #include <cmath>
 #include <limits>

>From 76b4a8a8ec33acf9f4c132072ad70422d6f09bd5 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Wed, 22 Jul 2026 12:24:03 +0200
Subject: [PATCH 21/25] fix: convert assert to static_assert

---
 libcxx/test/std/numerics/c.math/isgreater.pass.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 269bb31e016cf..6932a26c75f8d 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -82,10 +82,10 @@ int main(int, char**) {
 
   // Make sure we can call `std::isgreater` with mixed-type promotions with __promote_t<_A1, _A2>.
   {
-    assert(std::isgreater(2.0, 1));     // double vs int
-    assert(!std::isgreater(1, 2.0f));   // int vs float
-    assert(std::isgreater(2.0L, 1.0f)); // long double vs float
-    assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
+    static_assert(std::isgreater(2.0, 1));     // double vs int
+    static_assert(!std::isgreater(1, 2.0f));   // int vs float
+    static_assert(std::isgreater(2.0L, 1.0f)); // long double vs float
+    static_assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
   }
 
   return 0;

>From 36145d1a1740c144a180397eaa889873f752911c Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Wed, 22 Jul 2026 12:44:24 +0200
Subject: [PATCH 22/25] Fix: static_assertions on tests and remove of
 ConvertibleTo

---
 libcxx/test/std/numerics/c.math/isgreater.pass.cpp   | 12 +++++++-----
 .../test/std/numerics/c.math/isgreaterequal.pass.cpp | 12 +++++++-----
 libcxx/test/std/numerics/c.math/isless.pass.cpp      | 11 +++--------
 libcxx/test/std/numerics/c.math/islessequal.pass.cpp | 11 ++++++-----
 .../test/std/numerics/c.math/islessgreater.pass.cpp  |  5 -----
 libcxx/test/std/numerics/c.math/isunordered.pass.cpp |  5 -----
 6 files changed, 23 insertions(+), 33 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 6932a26c75f8d..781a9af90b153 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -71,21 +71,23 @@ struct TestInt {
   }
 };
 
-template <typename T>
-struct ConvertibleTo {
-  operator T() const { return T(1); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
 
   // Make sure we can call `std::isgreater` with mixed-type promotions with __promote_t<_A1, _A2>.
   {
+    assert(std::isgreater(2.0, 1));     // double vs int
+    assert(!std::isgreater(1, 2.0f));   // int vs float
+    assert(std::isgreater(2.0L, 1.0f)); // long double vs float
+    assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
+
+#if TEST_STD_VER >= 23
     static_assert(std::isgreater(2.0, 1));     // double vs int
     static_assert(!std::isgreater(1, 2.0f));   // int vs float
     static_assert(std::isgreater(2.0L, 1.0f)); // long double vs float
     static_assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
+#endif
   }
 
   return 0;
diff --git a/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
index 27fa43812812a..bc8b23d01cc7a 100644
--- a/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
@@ -69,11 +69,6 @@ struct TestInt {
   }
 };
 
-template <typename T>
-struct ConvertibleTo {
-  operator T() const { return T(1); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
@@ -84,6 +79,13 @@ int main(int, char**) {
     assert(!std::isgreaterequal(1, 2.0f));   // int vs float
     assert(std::isgreaterequal(2.0L, 1.0f)); // long double vs float
     assert(!std::isgreaterequal(std::numeric_limits<double>::quiet_NaN(), 0));
+
+#if TEST_STD_VER >= 23
+    static_assert(std::isgreaterequal(2.0, 1));     // double vs int
+    static_assert(!std::isgreaterequal(1, 2.0f));   // int vs float
+    static_assert(std::isgreaterequal(2.0L, 1.0f)); // long double vs float
+    static_assert(!std::isgreaterequal(std::numeric_limits<double>::quiet_NaN(), 0));
+#endif
   }
 
   return 0;
diff --git a/libcxx/test/std/numerics/c.math/isless.pass.cpp b/libcxx/test/std/numerics/c.math/isless.pass.cpp
index cc68a49beead9..bf341f90f3b38 100644
--- a/libcxx/test/std/numerics/c.math/isless.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isless.pass.cpp
@@ -65,20 +65,15 @@ struct TestInt {
   }
 };
 
-template <typename T>
-struct ConvertibleTo {
-  operator T() const { return T(1); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
 
   // Make sure we can call `std::isless` with mixed-type promotions with __promote_t<_A1, _A2>.
   {
-    assert(!std::isless(2.0, 1));     // double vs int
-    assert(std::isless(1, 2.0f));     // int vs float
-    assert(!std::isless(2.0L, 1.0f)); // long double vs float
+    static_assert(!std::isless(2.0, 1));     // double vs int
+    static_assert(std::isless(1, 2.0f));     // int vs float
+    static_assert(!std::isless(2.0L, 1.0f)); // long double vs float
   }
 
   return 0;
diff --git a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
index 5f58bbc993613..55a163f769148 100644
--- a/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
@@ -69,11 +69,6 @@ struct TestInt {
   }
 };
 
-template <typename T>
-struct ConvertibleTo {
-  operator T() const { return T(1); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
@@ -83,6 +78,12 @@ int main(int, char**) {
     assert(!std::islessequal(2.0, 1));     // double vs int
     assert(std::islessequal(1, 2.0f));     // int vs float
     assert(!std::islessequal(2.0L, 1.0f)); // long double vs float
+
+#if TEST_STD_VER >= 23
+    static_assert(!std::islessequal(2.0, 1));     // double vs int
+    static_assert(std::islessequal(1, 2.0f));     // int vs float
+    static_assert(!std::islessequal(2.0L, 1.0f)); // long double vs float
+#endif
   }
 
   return 0;
diff --git a/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp b/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
index 6a10708359bbe..2d92f0f60b5b8 100644
--- a/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
@@ -75,11 +75,6 @@ struct TestInt {
   }
 };
 
-template <typename T>
-struct ConvertibleTo {
-  operator T() const { return T(1); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
diff --git a/libcxx/test/std/numerics/c.math/isunordered.pass.cpp b/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
index 3f140106a423f..1f3d43f4c3e7c 100644
--- a/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
@@ -62,11 +62,6 @@ struct TestInt {
   }
 };
 
-template <typename T>
-struct ConvertibleTo {
-  operator T() const { return T(1); }
-};
-
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());

>From c1880a334e9391a2e6c0c52bbc98ce9bf77079b3 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Wed, 22 Jul 2026 17:12:18 +0200
Subject: [PATCH 23/25] fix: isless.pass.cpp

---
 libcxx/test/std/numerics/c.math/isless.pass.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libcxx/test/std/numerics/c.math/isless.pass.cpp b/libcxx/test/std/numerics/c.math/isless.pass.cpp
index bf341f90f3b38..3b5feb3f7bba3 100644
--- a/libcxx/test/std/numerics/c.math/isless.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isless.pass.cpp
@@ -71,9 +71,15 @@ int main(int, char**) {
 
   // Make sure we can call `std::isless` with mixed-type promotions with __promote_t<_A1, _A2>.
   {
+    assert(!std::isless(2.0, 1));     // double vs int
+    assert(std::isless(1, 2.0f));     // int vs float
+    assert(!std::isless(2.0L, 1.0f)); // long double vs float
+
+#if TEST_STD_VER >= 23
     static_assert(!std::isless(2.0, 1));     // double vs int
     static_assert(std::isless(1, 2.0f));     // int vs float
     static_assert(!std::isless(2.0L, 1.0f)); // long double vs float
+#endif
   }
 
   return 0;

>From bd9baa5755b01d5fd91750fcb6a3e2fe391563a0 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Wed, 22 Jul 2026 18:28:01 +0200
Subject: [PATCH 24/25] fix: isgreater.pass.cpp

---
 .../std/numerics/c.math/isgreater.pass.cpp    | 97 +++++++++----------
 1 file changed, 45 insertions(+), 52 deletions(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index 781a9af90b153..cc77a31861292 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -18,77 +18,70 @@
 
 struct TestFloat {
   template <class T>
-  static TEST_CONSTEXPR_CXX23 bool test() {
-    assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
-    assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
-    assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
-
-    assert(std::isgreater(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::max()));
-    assert(!std::isgreater(-std::numeric_limits<T>::infinity(), std::numeric_limits<T>::lowest()));
-    assert(!std::isgreater(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()));
-
-    assert(!std::isgreater(std::numeric_limits<T>::quiet_NaN(), T(0)));
-    assert(!std::isgreater(T(0), std::numeric_limits<T>::quiet_NaN()));
-    assert(!std::isgreater(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()));
-    assert(!std::isgreater(std::numeric_limits<T>::signaling_NaN(), T(0)));
-
-    return true;
-  }
-
-  template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
-    test<T>();
-#if TEST_STD_VER >= 23
-    static_assert(test<T>());
-#endif
+  TEST_CONSTEXPR_CXX23 void operator()() const {
+    using lim                    = std::numeric_limits<T>;
+    TEST_CONSTEXPR_CXX23 T max   = lim::max();
+    TEST_CONSTEXPR_CXX23 T low   = lim::lowest();
+    TEST_CONSTEXPR_CXX23 T inf   = lim::infinity();
+    TEST_CONSTEXPR_CXX23 T nan   = lim::quiet_NaN();
+    TEST_CONSTEXPR_CXX23 T s_nan = lim::signaling_NaN();
+
+    assert(std::isgreater(max, T(0)));
+    assert(!std::isgreater(T(0), max));
+    assert(!std::isgreater(max, max));
+
+    assert(std::isgreater(inf, max));
+    assert(!std::isgreater(-inf, low));
+    assert(!std::isgreater(inf, inf));
+
+    assert(!std::isgreater(nan, T(0)));
+    assert(!std::isgreater(T(0), nan));
+    assert(!std::isgreater(nan, nan));
+    assert(!std::isgreater(s_nan, T(0)));
   }
 };
 
 struct TestInt {
   template <class T>
-  static TEST_CONSTEXPR_CXX23 bool test() {
-    assert(std::isgreater(std::numeric_limits<T>::max(), T(0)));
-    assert(!std::isgreater(T(0), std::numeric_limits<T>::max()));
-    assert(!std::isgreater(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()));
+  TEST_CONSTEXPR_CXX23 void operator()() const {
+    using lim                  = std::numeric_limits<T>;
+    TEST_CONSTEXPR_CXX23 T max = lim::max();
+    TEST_CONSTEXPR_CXX23 T low = lim::lowest();
+
+    assert(std::isgreater(max, T(0)));
+    assert(!std::isgreater(T(0), max));
+    assert(!std::isgreater(max, max));
 
     assert(!std::isgreater(T(1), T(1)));
-    assert(!std::isgreater(std::numeric_limits<T>::lowest(), T(0)));
+    assert(!std::isgreater(low, T(0)));
 
     if (std::is_signed<T>::value) {
-      assert(std::isgreater(T(-1), std::numeric_limits<T>::lowest()));
-      assert(!std::isgreater(std::numeric_limits<T>::lowest(), T(-1)));
+      assert(std::isgreater(T(-1), low));
+      assert(!std::isgreater(low, T(-1)));
     }
-
-    return true;
-  }
-
-  template <class T>
-  TEST_CONSTEXPR_CXX23 void operator()() {
-    test<T>();
-#if TEST_STD_VER >= 23
-    static_assert(test<T>());
-#endif
   }
 };
 
-int main(int, char**) {
+TEST_CONSTEXPR_CXX23 bool test() {
+  using lim                    = std::numeric_limits<int>;
+  TEST_CONSTEXPR_CXX23 int nan = lim::quiet_NaN();
+
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
 
   // Make sure we can call `std::isgreater` with mixed-type promotions with __promote_t<_A1, _A2>.
-  {
-    assert(std::isgreater(2.0, 1));     // double vs int
-    assert(!std::isgreater(1, 2.0f));   // int vs float
-    assert(std::isgreater(2.0L, 1.0f)); // long double vs float
-    assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
+  assert(std::isgreater(2.0, 1));     // double vs int
+  assert(!std::isgreater(1, 2.0f));   // int vs float
+  assert(std::isgreater(2.0L, 1.0f)); // long double vs float
+  assert(!std::isgreater(nan, 0));    // NaN vs int
 
+  return true;
+}
+
+int main(int, char**) {
+  test();
 #if TEST_STD_VER >= 23
-    static_assert(std::isgreater(2.0, 1));     // double vs int
-    static_assert(!std::isgreater(1, 2.0f));   // int vs float
-    static_assert(std::isgreater(2.0L, 1.0f)); // long double vs float
-    static_assert(!std::isgreater(std::numeric_limits<double>::quiet_NaN(), 0));
+  static_assert(test());
 #endif
-  }
-
   return 0;
 }

>From dd9053a0cb40e9516d3e14835e12d9ebb0551793 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Wed, 22 Jul 2026 18:31:10 +0200
Subject: [PATCH 25/25] fix: std::is_signed<T>::value to
 std::numeric_limits<T>::is_signed

---
 libcxx/test/std/numerics/c.math/isgreater.pass.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
index cc77a31861292..303dd9f4870aa 100644
--- a/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -55,7 +55,7 @@ struct TestInt {
     assert(!std::isgreater(T(1), T(1)));
     assert(!std::isgreater(low, T(0)));
 
-    if (std::is_signed<T>::value) {
+    if (lim::is_signed) {
       assert(std::isgreater(T(-1), low));
       assert(!std::isgreater(low, T(-1)));
     }



More information about the libcxx-commits mailing list