Skip to content

[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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions libcxx/include/__math/abs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,37 @@ 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);
// 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ int main(int, char**) {
long double DummyLongDouble;

ASSERT_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(-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_CONSTEXPR_CXX23(std::labs(-1L) == 1L);
ASSERT_CONSTEXPR_CXX23(std::llabs(-1LL) == 1LL);
Expand Down
30 changes: 19 additions & 11 deletions libcxx/test/std/numerics/c.math/abs.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading