Skip to content

Commit

Permalink
[libc++] Use _Complex for multiplication and division of complex floa…
Browse files Browse the repository at this point in the history
…ting point types (llvm#83575)

This significantly simplifies the implementation and improves the
codegen. The only downside is that the accuracy can be marginally worse,
but that is up to the compiler to decide with this change, which means
it can be controlled by compiler flags.

Differential Revision: https://reviews.llvm.org/D155312
  • Loading branch information
philnik777 committed Jul 5, 2024
1 parent 2d0c4c3 commit 5aacf93
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 316 deletions.
155 changes: 0 additions & 155 deletions libcxx/include/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -610,161 +610,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __constexpr_isfinite(_A1 __lcpp_x)
return __builtin_isfinite(__lcpp_x);
}

_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI float __constexpr_copysign(float __x, float __y) _NOEXCEPT {
return __builtin_copysignf(__x, __y);
}

_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI double __constexpr_copysign(double __x, double __y) _NOEXCEPT {
return __builtin_copysign(__x, __y);
}

_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI long double
__constexpr_copysign(long double __x, long double __y) _NOEXCEPT {
return __builtin_copysignl(__x, __y);
}

template <class _A1,
class _A2,
__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0>
_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type
__constexpr_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 __builtin_copysign((__result_type)__x, (__result_type)__y);
}

inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float __constexpr_fabs(float __x) _NOEXCEPT {
return __builtin_fabsf(__x);
}

inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(double __x) _NOEXCEPT {
return __builtin_fabs(__x);
}

inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double __constexpr_fabs(long double __x) _NOEXCEPT {
return __builtin_fabsl(__x);
}

template <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(_Tp __x) _NOEXCEPT {
return __builtin_fabs(static_cast<double>(__x));
}

inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 float __constexpr_fmax(float __x, float __y) _NOEXCEPT {
#if !__has_constexpr_builtin(__builtin_fmaxf)
if (__libcpp_is_constant_evaluated()) {
if (std::__constexpr_isnan(__x))
return __y;
if (std::__constexpr_isnan(__y))
return __x;
return __x < __y ? __y : __x;
}
#endif
return __builtin_fmaxf(__x, __y);
}

inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 double __constexpr_fmax(double __x, double __y) _NOEXCEPT {
#if !__has_constexpr_builtin(__builtin_fmax)
if (__libcpp_is_constant_evaluated()) {
if (std::__constexpr_isnan(__x))
return __y;
if (std::__constexpr_isnan(__y))
return __x;
return __x < __y ? __y : __x;
}
#endif
return __builtin_fmax(__x, __y);
}

inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 long double
__constexpr_fmax(long double __x, long double __y) _NOEXCEPT {
#if !__has_constexpr_builtin(__builtin_fmaxl)
if (__libcpp_is_constant_evaluated()) {
if (std::__constexpr_isnan(__x))
return __y;
if (std::__constexpr_isnan(__y))
return __x;
return __x < __y ? __y : __x;
}
#endif
return __builtin_fmaxl(__x, __y);
}

template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value && is_arithmetic<_Up>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __promote<_Tp, _Up>::type
__constexpr_fmax(_Tp __x, _Up __y) _NOEXCEPT {
using __result_type = typename __promote<_Tp, _Up>::type;
return std::__constexpr_fmax(static_cast<__result_type>(__x), static_cast<__result_type>(__y));
}

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __constexpr_logb(_Tp __x) {
#if !__has_constexpr_builtin(__builtin_logb)
if (__libcpp_is_constant_evaluated()) {
if (__x == _Tp(0)) {
// raise FE_DIVBYZERO
return -numeric_limits<_Tp>::infinity();
}

if (std::__constexpr_isinf(__x))
return numeric_limits<_Tp>::infinity();

if (std::__constexpr_isnan(__x))
return numeric_limits<_Tp>::quiet_NaN();

__x = std::__constexpr_fabs(__x);
unsigned long long __exp = 0;
while (__x >= numeric_limits<_Tp>::radix) {
__x /= numeric_limits<_Tp>::radix;
__exp += 1;
}
return _Tp(__exp);
}
#endif // !__has_constexpr_builtin(__builtin_logb)
return __builtin_logb(__x);
}

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp __x, int __exp) {
#if !__has_constexpr_builtin(__builtin_scalbln)
if (__libcpp_is_constant_evaluated()) {
if (__x == _Tp(0))
return __x;

if (std::__constexpr_isinf(__x))
return __x;

if (__exp == _Tp(0))
return __x;

if (std::__constexpr_isnan(__x))
return numeric_limits<_Tp>::quiet_NaN();

_Tp __mult(1);
if (__exp > 0) {
__mult = numeric_limits<_Tp>::radix;
--__exp;
} else {
++__exp;
__exp = -__exp;
__mult /= numeric_limits<_Tp>::radix;
}

while (__exp > 0) {
if (!(__exp & 1)) {
__mult *= __mult;
__exp >>= 1;
} else {
__x *= __mult;
--__exp;
}
}
return __x;
}
#endif // !__has_constexpr_builtin(__builtin_scalbln)
return __builtin_scalbn(__x, __exp);
}

#if _LIBCPP_STD_VER >= 20
template <typename _Fp>
_LIBCPP_HIDE_FROM_ABI constexpr _Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept {
Expand Down
Loading

0 comments on commit 5aacf93

Please sign in to comment.