[libcxx-commits] [libcxx] a69addf - [libc++][math] Add `constexpr` to comparison functions (#210075)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jul 28 08:14:51 PDT 2026
Author: Lucas Mellone
Date: 2026-07-28T18:14:47+03:00
New Revision: a69addf4fb640c34fa8249543003c375247c4933
URL: https://github.com/llvm/llvm-project/commit/a69addf4fb640c34fa8249543003c375247c4933
DIFF: https://github.com/llvm/llvm-project/commit/a69addf4fb640c34fa8249543003c375247c4933.diff
LOG: [libc++][math] Add `constexpr` to comparison functions (#210075)
Implement `constexpr` to all comparison functions (`std::isgreater`,
`std::isgreaterequal`, `std::isless`, `std::islessequal`,
`std::islessgreater`, `std::isunordered`) as defined by
[P0533R9](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0533r9.pdf).
Towards https://github.com/llvm/llvm-project/issues/105174. Follows-up
https://github.com/llvm/llvm-project/pull/94118.
Added:
libcxx/test/std/numerics/c.math/isgreater.pass.cpp
libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
libcxx/test/std/numerics/c.math/isless.pass.cpp
libcxx/test/std/numerics/c.math/islessequal.pass.cpp
libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
libcxx/test/std/numerics/c.math/isunordered.pass.cpp
Modified:
libcxx/include/__math/traits.h
libcxx/include/cmath
libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index ff22cee7305d7..f32dc47ab1b1b 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -137,7 +137,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);
}
@@ -145,7 +146,8 @@ template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_ar
// 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);
}
@@ -153,7 +155,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);
}
@@ -161,7 +163,8 @@ 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);
}
@@ -169,7 +172,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_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);
}
@@ -177,7 +181,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_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);
}
@@ -216,42 +221,43 @@ 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);
}
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/include/cmath b/libcxx/include/cmath
index 992854b0490a3..e731f58e05f95 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -140,17 +140,17 @@ bool signbit(arithmetic x);
int fpclassify(arithmetic x); // constexpr since C++23
-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);
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 926ff37cddbfc..beca4907284ad 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,29 +227,29 @@ 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);
- 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).
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 455c03ef58d18..0ae3f5802e21f 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,29 +221,29 @@ 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);
- 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).
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..e09680edf50e1
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isgreater.pass.cpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(std::isgreater(lim::max(), T(0)));
+ assert(!std::isgreater(T(0), lim::max()));
+ assert(!std::isgreater(lim::max(), lim::max()));
+
+ assert(std::isgreater(lim::infinity(), lim::max()));
+ assert(!std::isgreater(-lim::infinity(), lim::lowest()));
+ assert(!std::isgreater(lim::infinity(), lim::infinity()));
+
+ assert(!std::isgreater(lim::quiet_NaN(), T(0)));
+ assert(!std::isgreater(T(0), lim::quiet_NaN()));
+ assert(!std::isgreater(lim::quiet_NaN(), lim::quiet_NaN()));
+ assert(!std::isgreater(lim::signaling_NaN(), T(0)));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(std::isgreater(lim::max(), T(0)));
+ assert(!std::isgreater(T(0), lim::max()));
+ assert(!std::isgreater(lim::max(), lim::max()));
+
+ assert(!std::isgreater(T(1), T(1)));
+ assert(!std::isgreater(lim::lowest(), T(0)));
+
+ if (lim::is_signed) {
+ assert(std::isgreater(T(-1), lim::lowest()));
+ assert(!std::isgreater(lim::lowest(), T(-1)));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ using lim = std::numeric_limits<double>;
+
+ 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.
+ {
+ 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(lim::quiet_NaN(), 0)); // NaN vs int
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#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
new file mode 100644
index 0000000000000..a1f03253247ca
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isgreaterequal.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 isgreaterequal(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(std::isgreaterequal(lim::max(), T(0)));
+ assert(!std::isgreaterequal(T(0), lim::max()));
+ assert(std::isgreaterequal(lim::max(), lim::max()));
+
+ assert(std::isgreaterequal(lim::infinity(), lim::max()));
+ assert(!std::isgreaterequal(-lim::infinity(), lim::lowest()));
+ assert(std::isgreaterequal(lim::infinity(), lim::infinity()));
+
+ assert(!std::isgreaterequal(lim::quiet_NaN(), T(0)));
+ assert(!std::isgreaterequal(T(0), lim::quiet_NaN()));
+ assert(!std::isgreaterequal(lim::signaling_NaN(), T(0)));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(std::isgreaterequal(lim::max(), T(0)));
+ assert(!std::isgreaterequal(T(0), lim::max()));
+ assert(std::isgreaterequal(lim::max(), lim::max()));
+
+ assert(std::isgreaterequal(T(1), T(1)));
+
+ if (std::is_signed<T>::value) {
+ assert(std::isgreaterequal(T(-1), lim::lowest()));
+ assert(!std::isgreaterequal(lim::lowest(), T(-1)));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ using lim = std::numeric_limits<double>;
+
+ 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.
+ {
+ 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(lim::quiet_NaN(), 0)); // NaN vs int
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#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
new file mode 100644
index 0000000000000..70f71500f4696
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isless.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(!std::isless(lim::max(), T(0)));
+ assert(std::isless(T(0), lim::max()));
+
+ assert(!std::isless(lim::infinity(), lim::max()));
+ assert(std::isless(-lim::infinity(), lim::lowest()));
+
+ assert(!std::isless(T(0), lim::quiet_NaN()));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(!std::isless(lim::max(), T(0)));
+ assert(std::isless(T(0), lim::max()));
+ assert(!std::isless(lim::max(), lim::max()));
+
+ assert(!std::isless(T(1), T(1)));
+
+ if (lim::is_signed) {
+ assert(!std::isless(T(-1), lim::lowest()));
+ assert(std::isless(lim::lowest(), T(-1)));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ using lim = std::numeric_limits<double>;
+
+ 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.
+ {
+ 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
+ assert(!std::isless(lim::quiet_NaN(), 1.0)); // NaN vs int
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#endif
+ return 0;
+}
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..34b5cacd584e5
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/islessequal.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 islessequal(floating-point-type x, floating-point-type y); // constexpr since C++23
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(!std::islessequal(lim::max(), T(0)));
+ assert(std::islessequal(T(0), lim::max()));
+ assert(std::islessequal(lim::max(), lim::max()));
+
+ assert(!std::islessequal(lim::infinity(), lim::max()));
+ assert(std::islessequal(-lim::infinity(), lim::lowest()));
+ assert(std::islessequal(lim::infinity(), lim::infinity()));
+
+ assert(!std::islessequal(lim::quiet_NaN(), T(0)));
+ assert(!std::islessequal(T(0), lim::quiet_NaN()));
+ assert(!std::islessequal(lim::signaling_NaN(), T(0)));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(!std::islessequal(lim::max(), T(0)));
+ assert(std::islessequal(T(0), lim::max()));
+ assert(std::islessequal(lim::max(), lim::max()));
+
+ assert(std::islessequal(T(1), T(1)));
+
+ if (lim::is_signed) {
+ assert(!std::islessequal(T(-1), lim::lowest()));
+ assert(std::islessequal(lim::lowest(), T(-1)));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ using lim = std::numeric_limits<double>;
+
+ 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.
+ {
+ 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
+ assert(!std::islessequal(lim::quiet_NaN(), 0)); // NaN vs int
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#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
new file mode 100644
index 0000000000000..86495f4a5b527
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/islessgreater.pass.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(std::islessgreater(T(1), T(2)));
+ assert(std::islessgreater(T(2), T(1)));
+ assert(!std::islessgreater(T(1), T(1)));
+
+ assert(!std::islessgreater(lim::infinity(), lim::infinity()));
+ assert(std::islessgreater(lim::infinity(), lim::max()));
+
+ assert(!std::islessgreater(lim::quiet_NaN(), T(0)));
+ assert(!std::islessgreater(T(0), lim::quiet_NaN()));
+ assert(!std::islessgreater(lim::quiet_NaN(), lim::quiet_NaN()));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ 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(lim::max(), T(0)));
+ assert(!std::islessgreater(lim::max(), lim::max()));
+
+ if (lim::is_signed) {
+ assert(std::islessgreater(T(-1), T(1)));
+ assert(std::islessgreater(lim::lowest(), T(0)));
+ assert(std::islessgreater(T(0), lim::lowest()));
+ assert(!std::islessgreater(lim::lowest(), lim::lowest()));
+ }
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ using lim = std::numeric_limits<double>;
+
+ types::for_each(types::floating_point_types(), TestFloat());
+ types::for_each(types::integral_types(), TestInt());
+
+ // Make sure we can call `std::islessgreater` with mixed-type promotions.
+ {
+ assert(std::islessgreater(2.0, 1)); // double vs int
+ assert(std::islessgreater(1, 2.0f)); // int vs float
+ assert(std::islessgreater(2.0L, 1.0f)); // long double vs float
+ assert(!std::islessgreater(lim::quiet_NaN(), 1.0)); // NaN vs int
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#endif
+ 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..bb13d46768a69
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isunordered.pass.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(!std::isunordered(T(1), T(2)));
+ assert(!std::isunordered(T(1), T(1)));
+
+ assert(std::isunordered(lim::quiet_NaN(), T(0)));
+ assert(std::isunordered(T(0), lim::quiet_NaN()));
+ assert(std::isunordered(lim::quiet_NaN(), lim::quiet_NaN()));
+
+ assert(std::isunordered(lim::signaling_NaN(), T(0)));
+ assert(!std::isunordered(lim::infinity(), lim::infinity()));
+ assert(!std::isunordered(lim::max(), lim::lowest()));
+ }
+};
+
+struct TestInt {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() const {
+ using lim = std::numeric_limits<T>;
+
+ assert(!std::isunordered(T(1), T(2)));
+ assert(!std::isunordered(T(1), T(1)));
+ assert(!std::isunordered(lim::max(), T(0)));
+ assert(!std::isunordered(lim::max(), lim::max()));
+ }
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+ using lim = std::numeric_limits<double>;
+
+ types::for_each(types::floating_point_types(), TestFloat());
+ types::for_each(types::integral_types(), TestInt());
+
+ // Make sure we can call `std::isunordered` with mixed-type promotions.
+ {
+ assert(!std::isunordered(2.0, 1)); // double vs int
+ assert(!std::isunordered(1, 2.0f)); // int vs float
+ assert(!std::isunordered(2.0L, 1.0f)); // long double vs float
+ assert(std::isunordered(lim::quiet_NaN(), 1.0)); // NaN vs int
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 23
+ static_assert(test());
+#endif
+ return 0;
+}
More information about the libcxx-commits
mailing list