[libcxx-commits] [libcxx] [libc++][math] Add `constexpr` for `std::signbit()` (PR #105946)
Robin Caloudis via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Aug 24 09:11:38 PDT 2024
https://github.com/robincaloudis updated https://github.com/llvm/llvm-project/pull/105946
>From 14817aea45b1511dbfaca2195afd706b38695d21 Mon Sep 17 00:00:00 2001
From: Robin Caloudis <robin.caloudis at gmx.de>
Date: Sat, 24 Aug 2024 18:00:25 +0200
Subject: [PATCH 1/3] Test constexpr for signbit()
---
.../c.math/constexpr-cxx23-clang.pass.cpp | 6 +-
.../c.math/constexpr-cxx23-gcc.pass.cpp | 6 +-
.../test/std/numerics/c.math/signbit.pass.cpp | 106 ++++++++++++++++++
3 files changed, 112 insertions(+), 6 deletions(-)
create mode 100644 libcxx/test/std/numerics/c.math/signbit.pass.cpp
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 a07260a34516f1..20887b8cf2678b 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
@@ -220,9 +220,9 @@ int main(int, char**) {
ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1);
ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
+ ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
+ 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);
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 8c481f41a945ed..d8779706bcee22 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
@@ -217,9 +217,9 @@ int main(int, char**) {
ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1);
ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
+ ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
+ 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);
diff --git a/libcxx/test/std/numerics/c.math/signbit.pass.cpp b/libcxx/test/std/numerics/c.math/signbit.pass.cpp
new file mode 100644
index 00000000000000..0d608dd979e0b4
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/signbit.pass.cpp
@@ -0,0 +1,106 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 signbit(floating-point-type x); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+ template <class T>
+ static TEST_CONSTEXPR_CXX23 bool test() {
+ assert(!std::signbit(T(0)));
+ assert(std::signbit(-T(0)));
+ assert(std::signbit(std::numeric_limits<T>::lowest()));
+ assert(!std::signbit(std::numeric_limits<T>::min()));
+ assert(!std::signbit(std::numeric_limits<T>::denorm_min()));
+ assert(!std::signbit(std::numeric_limits<T>::max()));
+ assert(!std::signbit(std::numeric_limits<T>::infinity()));
+ assert(std::signbit(-std::numeric_limits<T>::infinity()));
+ assert(!std::signbit(std::numeric_limits<T>::quiet_NaN()));
+ assert(!std::signbit(std::numeric_limits<T>::signaling_NaN()));
+
+ return true;
+ }
+
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test<T>();
+#if TEST_STD_VER >= 23
+ static_assert(test<T>());
+#endif
+ }
+};
+
+struct TestUnsignedIntAndChar {
+ template <class T>
+ static TEST_CONSTEXPR_CXX23 bool test() {
+ assert(!std::signbit(std::numeric_limits<T>::max()));
+ assert(!std::signbit(std::numeric_limits<T>::lowest()));
+ assert(!std::signbit(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 TestSignedIntAndChar {
+ template <class T>
+ static TEST_CONSTEXPR_CXX23 bool test() {
+ assert(!std::signbit(std::numeric_limits<T>::max()));
+ assert(std::signbit(std::numeric_limits<T>::lowest()));
+ assert(!std::signbit(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(); }
+};
+
+int main(int, char**) {
+ types::for_each(types::floating_point_types(), TestFloat());
+ types::for_each(types::concatenate_t<types::unsigned_integer_types, types::type_list<char8_t, char16_t, char32_t>>(),
+ TestUnsignedIntAndChar());
+ types::for_each(types::concatenate_t<types::signed_integer_types, types::type_list<char, wchar_t>>(), TestSignedIntAndChar());
+
+ // Make sure we can call `std::signbit` with convertible types. This checks
+ // whether overloads for all cv-unqualified floating-point types are working
+ // as expected.
+ {
+ assert(!std::signbit(ConvertibleTo<float>()));
+ assert(!std::signbit(ConvertibleTo<double>()));
+ assert(!std::signbit(ConvertibleTo<long double>()));
+ }
+
+ return 0;
+}
>From 85c2ef78437524ca2e87838eb84a5a0cb9dc8664 Mon Sep 17 00:00:00 2001
From: Robin Caloudis <robin.caloudis at gmx.de>
Date: Sat, 24 Aug 2024 18:00:56 +0200
Subject: [PATCH 2/3] Add constexpr for signbit()
---
libcxx/include/__math/traits.h | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 35c283cc9e21ce..deff6139493032 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -29,17 +29,29 @@ namespace __math {
// signbit
template <class _A1, __enable_if_t<is_floating_point<_A1>::value, int> = 0>
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT {
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT {
+ return __builtin_signbit(__x);
+}
+
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT {
+ return __builtin_signbit(__x);
+}
+
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT {
+ return __builtin_signbit(__x);
+}
+
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT {
return __builtin_signbit(__x);
}
template <class _A1, __enable_if_t<is_integral<_A1>::value && is_signed<_A1>::value, int> = 0>
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT {
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT {
return __x < 0;
}
template <class _A1, __enable_if_t<is_integral<_A1>::value && !is_signed<_A1>::value, int> = 0>
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT {
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT {
return false;
}
>From 46db6d4b42e6cd33c0cc764755f3e3360c440c5f Mon Sep 17 00:00:00 2001
From: Robin Caloudis <robin.caloudis at gmx.de>
Date: Sat, 24 Aug 2024 18:01:43 +0200
Subject: [PATCH 3/3] Update cxx23 status
---
libcxx/docs/Status/Cxx23.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/docs/Status/Cxx23.rst b/libcxx/docs/Status/Cxx23.rst
index 1a8d43bff74752..e977da82884269 100644
--- a/libcxx/docs/Status/Cxx23.rst
+++ b/libcxx/docs/Status/Cxx23.rst
@@ -38,7 +38,7 @@ Paper Status
.. note::
- .. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented.
+ .. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan``, ``isnormal`` and ``signbit`` are implemented.
.. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but
clang doesn't issue a diagnostic for deprecated using template declarations.
.. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
More information about the libcxx-commits
mailing list