This is a spin-off from D79555 review, that with this patch will be able to use __libcpp_copysign instead of adhoc __copysign_constexpr helper.
Details
- Reviewers
ldionne - Group Reviewers
Restricted Project - Commits
- rG1daf0e22562c: [libc++] Add `__libcpp_copysign` conditionally constexpr overloads.
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
libcxx/include/math.h | ||
---|---|---|
1169–1190 | If anyone has an idea about how to replace these 3 overloads with something simpler, without breaking things, I'm all ears. template <class _A1, class _A2> auto copysign(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { return __copysign(__lcpp_x, __lcpp_y); } doesn't work before C++14 because of auto. |
libcxx/include/math.h | ||
---|---|---|
1169–1190 | At least it needs more comments about the design constraints ;) because I don't see why there are overloads only for float and long double, but not double. What's wrong with simply...? #if __has_builtin(__builtin_copysignf) inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float copysign(float __x, float __y) _NOEXCEPT { return __builtin_copysignf(__x, __y); } #else inline _LIBCPP_INLINE_VISIBILITY float copysign(float __x, float __y) _NOEXCEPT { return ::copysignf(__x, __y); } #endif #if __has_builtin(__builtin_copysign) inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double copysign(double __x, double __y) _NOEXCEPT { return __builtin_copysign(__x, __y); } #else inline _LIBCPP_INLINE_VISIBILITY double copysign(double __x, double __y) _NOEXCEPT { return ::copysign(__x, __y); } #endif #if __has_builtin(__builtin_copysignl) inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double copysign(long double __x, long double __y) _NOEXCEPT { return __builtin_copysignl(__x, __y); } #else inline _LIBCPP_INLINE_VISIBILITY long double copysign(long double __x, long double __y) _NOEXCEPT { return ::copysignl(__x, __y); } #endif inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename _EnableIf< is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, __promote<_A1, _A2> >::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { typedef typename std::__promote<_A1, _A2>::type __result_type; static_assert((!(std::_IsSame<_A1, __result_type>::value && std::_IsSame<_A2, __result_type>::value)), ""); return _VSTD::copysign(__result_type(__x), __result_type(__y)); } It's about 6 lines longer than what's there now, but I think it's massively simpler. |
I'm not a big fan of the duplication, but unless we find a way to improve that, I think this LGTM (I mean.. I don't see a better way right now). Requesting changes until we've resolved the discussion about duplication.
Thanks for working on this, I think it'll make the constexpr-for-complex patch better.
libcxx/include/math.h | ||
---|---|---|
1169–1190 | We don't want to make copysign constexpr, only the library-internal version __copysign. Regarding an overload for double, it is handled by the _A1, _A2 overload which ends up calling ::copysign(double, double) from the C library. Or were you thinking about something else? | |
1171 | _VSTD:: here and below (it doesn't make a difference here, but let's be consistent). |
libcxx/include/math.h | ||
---|---|---|
1169–1190 |
Oh, I see. In that case, my suggestion would make the code ~2x as long as it was before; and so I have no suggestion better than this PR.
My godbolt testing suggests that copysign(double, double) is not handled by the _A1, _A2 overload, but instead by using ::copysign _LIBCPP_USING_IF_EXISTS; elsewhere in this file... Ah, but __copysign(double, double) is handled by the template. Which is fine (only) because users don't call __copysign directly. But actually, does libc++ ever call __copysign(_A1, _A2) directly? Maybe the templated version should be provided only for users, i.e. template copysign because the Standard says we have to, but do not template __copysign. |
libcxx/include/math.h | ||
---|---|---|
1169–1190 |
Actually, why don't we? |
Regarding naming, maybe I should rename __copysign to __libcpp_copysign to match what is done currently?
- Rename to libcpp_copysign due to clashes with Linux ::copysign. Add double overload.
libcxx/include/math.h | ||
---|---|---|
1143 | FYI, this overload is necessary because, as Arthur correctly mentioned, copysign(double, double) is handled by using ::copysign _LIBCPP_USING_IF_EXISTS;, but there's no equivalent for __libcpp_copysign and using __libcpp_copysign(double, double) provokes an assertion failure in the template function because both types are the same. |
LGTM pending CI.
libcxx/include/math.h | ||
---|---|---|
1169–1190 |
|
libcxx/include/math.h | ||
---|---|---|
1169–1190 | Fair enough. Thank you for the answer. |
FYI, this overload is necessary because, as Arthur correctly mentioned, copysign(double, double) is handled by using ::copysign _LIBCPP_USING_IF_EXISTS;, but there's no equivalent for __libcpp_copysign and using __libcpp_copysign(double, double) provokes an assertion failure in the template function because both types are the same.