-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[libc++][math] Add constexpr for std::abs() #146633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-libcxx Author: Arjun Patel (arjunUpatel) ChangesImplement Full diff: https://github.com/llvm/llvm-project/pull/146633.diff 3 Files Affected:
diff --git a/libcxx/include/__math/abs.h b/libcxx/include/__math/abs.h
index b780159f11ebf..a1d5854ac8878 100644
--- a/libcxx/include/__math/abs.h
+++ b/libcxx/include/__math/abs.h
@@ -41,25 +41,25 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
// abs
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); }
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT { return __builtin_fabs(__x); }
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); }
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT { return __builtin_fabs(__x); }
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long double abs(long double __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long double abs(long double __x) _NOEXCEPT {
return __builtin_fabsl(__x);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline int abs(int __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline int abs(int __x) _NOEXCEPT {
return __builtin_abs(__x);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long abs(long __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long abs(long __x) _NOEXCEPT {
return __builtin_labs(__x);
}
template <class = int>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI inline long long abs(long long __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long long abs(long long __x) _NOEXCEPT {
return __builtin_llabs(__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 3f17f21e8c108..64164240c8564 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
@@ -40,12 +40,12 @@ int main(int, char**) {
double DummyDouble;
long double DummyLongDouble;
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1);
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
ASSERT_NOT_CONSTEXPR_CXX23(std::labs(-1L) == 1L);
ASSERT_NOT_CONSTEXPR_CXX23(std::llabs(-1LL) == 1LL);
diff --git a/libcxx/test/std/numerics/c.math/abs.pass.cpp b/libcxx/test/std/numerics/c.math/abs.pass.cpp
index 51aee6e986836..908620b2a3290 100644
--- a/libcxx/test/std/numerics/c.math/abs.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/abs.pass.cpp
@@ -20,21 +20,29 @@ struct correct_size_int {
};
template <class Source, class Result>
-void test_abs() {
- Source neg_val = -5;
- Source pos_val = 5;
- Result res = 5;
+TEST_CONSTEXPR_CXX23 void test_abs() {
+ TEST_CONSTEXPR_CXX23 Source neg_val = -5;
+ TEST_CONSTEXPR_CXX23 Source pos_val = 5;
+ TEST_CONSTEXPR_CXX23 Result res = 5;
ASSERT_SAME_TYPE(decltype(std::abs(neg_val)), Result);
-
- assert(std::abs(neg_val) == res);
- assert(std::abs(pos_val) == res);
+ #if TEST_STD_VER >= 23
+ static_assert(std::abs(neg_val) == res);
+ static_assert(std::abs(pos_val) == res);
+ #else
+ assert(std::abs(neg_val) == res);
+ assert(std::abs(pos_val) == res);
+ #endif
}
-void test_big() {
- long long int big_value = std::numeric_limits<long long int>::max(); // a value too big for ints to store
- long long int negative_big_value = -big_value;
- assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+TEST_CONSTEXPR_CXX23 void test_big() {
+ TEST_CONSTEXPR_CXX23 long long int big_value = std::numeric_limits<long long int>::max(); // a value too big for ints to store
+ TEST_CONSTEXPR_CXX23 long long int negative_big_value = -big_value;
+ #if TEST_STD_VER >= 23
+ static_assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+ #else
+ assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+ #endif
}
// The following is helpful to keep in mind:
|
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions h,cpp -- libcxx/include/__math/abs.h libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp libcxx/test/std/numerics/c.math/abs.pass.cpp View the diff from clang-format here.diff --git a/libcxx/include/__math/abs.h b/libcxx/include/__math/abs.h
index a1d5854ac..cf047df68 100644
--- a/libcxx/include/__math/abs.h
+++ b/libcxx/include/__math/abs.h
@@ -41,10 +41,15 @@ template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
// abs
-[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); }
-[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT { return __builtin_fabs(__x); }
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline float abs(float __x) _NOEXCEPT {
+ return __builtin_fabsf(__x);
+}
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline double abs(double __x) _NOEXCEPT {
+ return __builtin_fabs(__x);
+}
-[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long double abs(long double __x) _NOEXCEPT {
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline long double
+abs(long double __x) _NOEXCEPT {
return __builtin_fabsl(__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 675270264..8988491f9 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
@@ -40,37 +40,37 @@ int main(int, char**) {
double DummyDouble;
long double DummyLongDouble;
- // TODO(LLVM 22): Remove `__has_constexpr_builtin` conditional once support for Clang 19 is dropped.
- #if __has_constexpr_builtin(__builtin_abs)
- ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1);
- #else
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1) == 1);
- #endif
- #if __has_constexpr_builtin(__builtin_labs)
- ASSERT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
- #else
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
- #endif
- #if __has_constexpr_builtin(__builtin_llabs)
- ASSERT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
- #else
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
- #endif
- #if __has_constexpr_builtin(__builtin_fabsf)
- ASSERT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
- #else
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
- #endif
- #if __has_constexpr_builtin(__builtin_fabs)
- ASSERT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
- #else
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
- #endif
- #if __has_constexpr_builtin(__builtin_fabsl)
- ASSERT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
- #else
- ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
- #endif
+// TODO(LLVM 22): Remove `__has_constexpr_builtin` conditional once support for Clang 19 is dropped.
+#if __has_constexpr_builtin(__builtin_abs)
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1);
+#else
+ ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1) == 1);
+#endif
+#if __has_constexpr_builtin(__builtin_labs)
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
+#else
+ ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1L) == 1L);
+#endif
+#if __has_constexpr_builtin(__builtin_llabs)
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
+#else
+ ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1LL) == 1LL);
+#endif
+#if __has_constexpr_builtin(__builtin_fabsf)
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
+#else
+ ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f);
+#endif
+#if __has_constexpr_builtin(__builtin_fabs)
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
+#else
+ ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0);
+#endif
+#if __has_constexpr_builtin(__builtin_fabsl)
+ ASSERT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+#else
+ ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L);
+#endif
ASSERT_NOT_CONSTEXPR_CXX23(std::labs(-1L) == 1L);
ASSERT_NOT_CONSTEXPR_CXX23(std::llabs(-1LL) == 1LL);
diff --git a/libcxx/test/std/numerics/c.math/abs.pass.cpp b/libcxx/test/std/numerics/c.math/abs.pass.cpp
index 908620b2a..6c9456f0d 100644
--- a/libcxx/test/std/numerics/c.math/abs.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/abs.pass.cpp
@@ -26,23 +26,24 @@ TEST_CONSTEXPR_CXX23 void test_abs() {
TEST_CONSTEXPR_CXX23 Result res = 5;
ASSERT_SAME_TYPE(decltype(std::abs(neg_val)), Result);
- #if TEST_STD_VER >= 23
- static_assert(std::abs(neg_val) == res);
- static_assert(std::abs(pos_val) == res);
- #else
- assert(std::abs(neg_val) == res);
- assert(std::abs(pos_val) == res);
- #endif
+#if TEST_STD_VER >= 23
+ static_assert(std::abs(neg_val) == res);
+ static_assert(std::abs(pos_val) == res);
+#else
+ assert(std::abs(neg_val) == res);
+ assert(std::abs(pos_val) == res);
+#endif
}
TEST_CONSTEXPR_CXX23 void test_big() {
- TEST_CONSTEXPR_CXX23 long long int big_value = std::numeric_limits<long long int>::max(); // a value too big for ints to store
+ TEST_CONSTEXPR_CXX23 long long int big_value =
+ std::numeric_limits<long long int>::max(); // a value too big for ints to store
TEST_CONSTEXPR_CXX23 long long int negative_big_value = -big_value;
- #if TEST_STD_VER >= 23
- static_assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
- #else
- assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
- #endif
+#if TEST_STD_VER >= 23
+ static_assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+#else
+ assert(std::abs(negative_big_value) == big_value); // make sure it doesn't get casted to a smaller type
+#endif
}
// The following is helpful to keep in mind:
|
ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0f) == 1.0f); | ||
ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0) == 1.0); | ||
ASSERT_NOT_CONSTEXPR_CXX23(std::abs(-1.0L) == 1.0L); | ||
ASSERT_CONSTEXPR_CXX23(std::abs(-1) == 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is problematic. Currently, this abs
overload is from the underlying C standard library and not constexpr-since-C++23 yet. I guess we can avoid testing this overload to make this PR proceed more quickly.
I'm really not sure whether we want to do this right now. It seems very weird to me to sometimes have constexpr support and sometimes not, depending on what you include. |
Implement
constexpr
forstd::abs()
as defined by P0533R9 (new C++23 feature). Progress tracked by #105174