[libcxx-commits] [libcxx] [libc++][math] Add `constexpr` to classification / comparison functions (PR #210075)
Lucas Mellone via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jul 17 14:57: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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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;
+}
More information about the libcxx-commits
mailing list