diff --git a/libcxx/include/cmath b/libcxx/include/cmath --- a/libcxx/include/cmath +++ b/libcxx/include/cmath @@ -628,161 +628,6 @@ 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 -_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI - typename std::__enable_if_t::value && std::is_arithmetic<_A2>::value, - std::__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 ::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(_Tp __x) _NOEXCEPT { - return __builtin_fabs(static_cast(__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 ::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 -_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 -_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 _LIBCPP_HIDE_FROM_ABI constexpr diff --git a/libcxx/include/complex b/libcxx/include/complex --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -250,8 +250,21 @@ template class _LIBCPP_TEMPLATE_VIS complex; -template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); -template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> +operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); + +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> +operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); + +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> +operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); + +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> +operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); template class _LIBCPP_TEMPLATE_VIS complex @@ -315,6 +328,23 @@ template<> class _LIBCPP_TEMPLATE_VIS complex; template<> class _LIBCPP_TEMPLATE_VIS complex; +struct __from_builtin_tag {}; + +template +using __complex_t = + __conditional_t::value, + _Complex float, + __conditional_t::value, _Complex double, _Complex long double> >; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __complex_t<_Tp> __make_complex(_Tp __re, _Tp __im) { +#if __has_builtin(__builtin_complex) + return __builtin_complex(__re, __im); +#else + return __complex_t<_Tp>{__re, __im}; +#endif +} + template<> class _LIBCPP_TEMPLATE_VIS complex { @@ -325,6 +355,10 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(float __re = 0.0f, float __im = 0.0f) : __re_(__re), __im_(__im) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex float __v) + : __re_(__real__ __v), __im_(__imag__ __v) {} + _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY @@ -336,6 +370,12 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Complex float __builtin() const { return std::__make_complex(__re_, __im_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __builtin(_Complex float __f) { + __re_ = __real__ __f; + __im_ = __imag__ __f; + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (float __re) {__re_ = __re; __im_ = value_type(); return *this;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(float __re) {__re_ += __re; return *this;} @@ -383,6 +423,10 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(double __re = 0.0, double __im = 0.0) : __re_(__re), __im_(__im) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex double __v) + : __re_(__real__ __v), __im_(__imag__ __v) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY @@ -394,6 +438,15 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Complex double __builtin() const { + return std::__make_complex(__re_, __im_); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __builtin(_Complex double __f) { + __re_ = __real__ __f; + __im_ = __imag__ __f; + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (double __re) {__re_ = __re; __im_ = value_type(); return *this;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(double __re) {__re_ += __re; return *this;} @@ -441,6 +494,10 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(long double __re = 0.0L, long double __im = 0.0L) : __re_(__re), __im_(__im) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex long double __v) + : __re_(__real__ __v), __im_(__imag__ __v) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY @@ -452,6 +509,15 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Complex long double __builtin() const { + return std::__make_complex(__re_, __im_); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __builtin(_Complex long double __f) { + __re_ = __real__ __f; + __im_ = __imag__ __f; + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (long double __re) {__re_ = __re; __im_ = value_type(); return *this;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(long double __re) {__re_ += __re; return *this;} @@ -581,7 +647,13 @@ return __t; } -template +template ::value, int> > +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> +operator*(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) { + return complex<_Tp>(__from_builtin_tag(), __lhs.__builtin() * __rhs.__builtin()); +} + +template::value, int> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) { @@ -590,87 +662,7 @@ _Tp __c = __w.real(); _Tp __d = __w.imag(); - // Avoid floating point operations that are invalid during constant evaluation - if (__libcpp_is_constant_evaluated()) { - bool __z_zero = __a == _Tp(0) && __b == _Tp(0); - bool __w_zero = __c == _Tp(0) && __d == _Tp(0); - bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b); - bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d); - bool __z_nan = !__z_inf && ( - (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) - || (std::__constexpr_isnan(__a) && __b == _Tp(0)) - || (__a == _Tp(0) && std::__constexpr_isnan(__b)) - ); - bool __w_nan = !__w_inf && ( - (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) - || (std::__constexpr_isnan(__c) && __d == _Tp(0)) - || (__c == _Tp(0) && std::__constexpr_isnan(__d)) - ); - if (__z_nan || __w_nan) { - return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); - } - if (__z_inf || __w_inf) { - if (__z_zero || __w_zero) { - return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); - } - return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); - } - bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b)); - bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d)); - if (__z_nonzero_nan || __w_nonzero_nan) { - return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); - } - } - - _Tp __ac = __a * __c; - _Tp __bd = __b * __d; - _Tp __ad = __a * __d; - _Tp __bc = __b * __c; - _Tp __x = __ac - __bd; - _Tp __y = __ad + __bc; - if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) - { - bool __recalc = false; - if (std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) - { - __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); - __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); - if (std::__constexpr_isnan(__c)) - __c = std::__constexpr_copysign(_Tp(0), __c); - if (std::__constexpr_isnan(__d)) - __d = std::__constexpr_copysign(_Tp(0), __d); - __recalc = true; - } - if (std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d)) - { - __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); - __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); - if (std::__constexpr_isnan(__a)) - __a = std::__constexpr_copysign(_Tp(0), __a); - if (std::__constexpr_isnan(__b)) - __b = std::__constexpr_copysign(_Tp(0), __b); - __recalc = true; - } - if (!__recalc && (std::__constexpr_isinf(__ac) || std::__constexpr_isinf(__bd) || - std::__constexpr_isinf(__ad) || std::__constexpr_isinf(__bc))) - { - if (std::__constexpr_isnan(__a)) - __a = std::__constexpr_copysign(_Tp(0), __a); - if (std::__constexpr_isnan(__b)) - __b = std::__constexpr_copysign(_Tp(0), __b); - if (std::__constexpr_isnan(__c)) - __c = std::__constexpr_copysign(_Tp(0), __c); - if (std::__constexpr_isnan(__d)) - __d = std::__constexpr_copysign(_Tp(0), __d); - __recalc = true; - } - if (__recalc) - { - __x = _Tp(INFINITY) * (__a * __c - __b * __d); - __y = _Tp(INFINITY) * (__a * __d + __b * __c); - } - } - return complex<_Tp>(__x, __y); + return complex<_Tp>((__a * __c) - (__b * __d), (__a * __d) + (__b * __c)); } template @@ -693,88 +685,23 @@ return __t; } -template +template ::value, int> > +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> +operator/(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) { + return complex<_Tp>(__from_builtin_tag(), __lhs.__builtin() / __rhs.__builtin()); +} + +template::value, int> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) { - int __ilogbw = 0; _Tp __a = __z.real(); _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); - _Tp __logbw = std::__constexpr_logb(std::__constexpr_fmax(std::__constexpr_fabs(__c), std::__constexpr_fabs(__d))); - if (std::__constexpr_isfinite(__logbw)) - { - __ilogbw = static_cast(__logbw); - __c = std::__constexpr_scalbn(__c, -__ilogbw); - __d = std::__constexpr_scalbn(__d, -__ilogbw); - } - - // Avoid floating point operations that are invalid during constant evaluation - if (__libcpp_is_constant_evaluated()) { - bool __z_zero = __a == _Tp(0) && __b == _Tp(0); - bool __w_zero = __c == _Tp(0) && __d == _Tp(0); - bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b); - bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d); - bool __z_nan = !__z_inf && ( - (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) - || (std::__constexpr_isnan(__a) && __b == _Tp(0)) - || (__a == _Tp(0) && std::__constexpr_isnan(__b)) - ); - bool __w_nan = !__w_inf && ( - (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) - || (std::__constexpr_isnan(__c) && __d == _Tp(0)) - || (__c == _Tp(0) && std::__constexpr_isnan(__d)) - ); - if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) { - return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); - } - bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b)); - bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d)); - if (__z_nonzero_nan || __w_nonzero_nan) { - if (__w_zero) { - return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); - } - return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); - } - if (__w_inf) { - return complex<_Tp>(_Tp(0), _Tp(0)); - } - if (__z_inf) { - return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); - } - if (__w_zero) { - if (__z_zero) { - return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); - } - return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); - } - } _Tp __denom = __c * __c + __d * __d; - _Tp __x = std::__constexpr_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); - _Tp __y = std::__constexpr_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); - if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) - { - if ((__denom == _Tp(0)) && (!std::__constexpr_isnan(__a) || !std::__constexpr_isnan(__b))) - { - __x = std::__constexpr_copysign(_Tp(INFINITY), __c) * __a; - __y = std::__constexpr_copysign(_Tp(INFINITY), __c) * __b; - } else if ((std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) && std::__constexpr_isfinite(__c) && - std::__constexpr_isfinite(__d)) { - __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); - __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); - __x = _Tp(INFINITY) * (__a * __c + __b * __d); - __y = _Tp(INFINITY) * (__b * __c - __a * __d); - } else if (std::__constexpr_isinf(__logbw) && __logbw > _Tp(0) && std::__constexpr_isfinite(__a) && - std::__constexpr_isfinite(__b)) { - __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); - __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); - __x = _Tp(0) * (__a * __c + __b * __d); - __y = _Tp(0) * (__b * __c - __a * __d); - } - } - return complex<_Tp>(__x, __y); + return complex<_Tp>((__a * __c + __b * __d) / __denom, (__b * __c - __a * __d) / __denom); } template diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp @@ -10,9 +10,10 @@ // complex& operator/=(const complex& rhs); // constexpr in C++20 -#include #include +#include +#include "floating_pointer_helpers.h" #include "test_macros.h" template @@ -22,28 +23,28 @@ { std::complex c(-4, 7.5); const std::complex c2(1.5, 2.5); - assert(c.real() == -4); - assert(c.imag() == 7.5); + assert(is_close(c.real(), T(-4))); + assert(is_close(c.imag(), T(7.5))); c /= c2; - assert(c.real() == 1.5); - assert(c.imag() == 2.5); + assert(is_close(c.real(), T(1.5))); + assert(is_close(c.imag(), T(2.5))); c /= c2; - assert(c.real() == 1); - assert(c.imag() == 0); + assert(is_close(c.real(), T(1))); + assert(is_close(c.imag(), T(0))); std::complex c3; c3 = c; std::complex ic (1,1); c3 /= ic; - assert(c3.real() == 0.5); - assert(c3.imag() == -0.5); + assert(is_close(c3.real(), T(0.5))); + assert(is_close(c3.imag(), T(-0.5))); c3 = c; std::complex fc (1,1); c3 /= fc; - assert(c3.real() == 0.5); - assert(c3.imag() == -0.5); + assert(is_close(c3.real(), T(0.5))); + assert(is_close(c3.imag(), T(-0.5))); return true; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp @@ -12,11 +12,12 @@ // complex // operator/(const complex& lhs, const complex& rhs); // constexpr in C++20 -// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000 +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000 -#include #include +#include +#include "floating_pointer_helpers.h" #include "test_macros.h" #include "../cases.h" @@ -27,7 +28,9 @@ { const std::complex lhs(-4.0, 7.5); const std::complex rhs(1.5, 2.5); - assert(lhs / rhs == std::complex(1.5, 2.5)); + const std::complex c = lhs / rhs; + assert(is_close(c.real(), T(1.5))); + assert(is_close(c.imag(), T(2.5))); return true; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp @@ -12,7 +12,7 @@ // complex // operator*(const complex& lhs, const complex& rhs); // constexpr in C++20 -// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000 +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000 #include #include diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp @@ -24,7 +24,11 @@ { const T lhs(-8.5); const std::complex rhs(1.5, 2.5); - assert(lhs / rhs == std::complex(-1.5, 2.5)); + const std::complex c = lhs / rhs; + assert(c.real() >= T(-1.500000000000001)); + assert(c.real() <= T(-1.499999999999999)); + assert(c.imag() >= T(2.499999999999999)); + assert(c.imag() <= T(2.500000000000001)); return true; } diff --git a/libcxx/test/support/floating_pointer_helpers.h b/libcxx/test/support/floating_pointer_helpers.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/floating_pointer_helpers.h @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_SUPPORT_FLOATING_POINT_HELPERS_H +#define TEST_SUPPORT_FLOATING_POINT_HELPERS_H + +#include + +#include "test_macros.h" + +template +TEST_CONSTEXPR_CXX20 bool is_close(T v, T comp) { + return v <= comp + std::numeric_limits::epsilon() && v >= comp - std::numeric_limits::epsilon(); +} + +#endif // TEST_SUPPORT_FLOATING_POINT_HELPERS_H