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,8 @@ template<> class _LIBCPP_TEMPLATE_VIS complex; template<> class _LIBCPP_TEMPLATE_VIS complex; +struct __from_builtin_tag {}; + template<> class _LIBCPP_TEMPLATE_VIS complex { @@ -325,6 +340,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 +355,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 __builtin_complex(__re_, __im_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 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 +408,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 +423,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 __builtin_complex(__re_, __im_); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 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 +479,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 +494,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 __builtin_complex(__re_, __im_); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 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 +632,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 +647,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,7 +670,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) { @@ -703,77 +686,13 @@ _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())); - } - } + __ilogbw = static_cast(__logbw); + __c = std::__constexpr_scalbn(__c, -__ilogbw); + __d = std::__constexpr_scalbn(__d, -__ilogbw); _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); }