From 0e2c5510e001e5ccbde9e4b7df757e2bba2fdb00 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 16 Nov 2022 14:45:40 +0100 Subject: [PATCH] libstdc++: Fix up for extended floating point types [PR107649] As filed by Jonathan in the PR, I've screwed up the requires syntax in the extended floating point specialization: - requires(__complex_type<_Tp>::type) + requires requires { typename __complex_type<_Tp>::type; } and doing this change resulted in lots of errors because __complex_whatever overfloads from extended floating point types were declared after the templates which used them. The following patch fixes that. Bootstrapped/regtested on x86_64-linux and i686-linux, additionally I've tested that with _GLIBCXX_HAVE_FLOAT128_MATH not being defined while __STDCPP_FLOAT128_T__ defined one can still use std::complex for basic arithmetic etc., just one can't expect std::sin etc. to work in that case (because we don't have any implementation). 2022-11-16 Jakub Jelinek Jonathan Wakely PR libstdc++/107649 * include/std/complex (__complex_abs, __complex_arg, __complex_cos, __complex_cosh, __complex_exp, __complex_log, __complex_sin, __complex_sinh, __complex_sqrt, __complex_tan, __complex_tanh, __complex_pow): Move __complex__ _Float{16,32,64,128} and __complex__ decltype(0.0bf16) overloads earlier in the file. (complex): Fix up requires on the partial specialization for extended float types. (__complex_acos, __complex_asin, __complex_atan, __complex_acosh, __complex_asinh, __complex_atanh): Move __complex__ _Float{16,32,64,128} and __complex__ decltype(0.0bf16) overloads earlier in the file. --- libstdc++-v3/include/std/complex | 1546 +++++++++++++++++++------------------- 1 file changed, 773 insertions(+), 773 deletions(-) diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index da2df91..7fed8a7 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -598,746 +598,746 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __z.imag(); } #endif - // 26.2.7/3 abs(__z): Returns the magnitude of __z. - template - inline _Tp - __complex_abs(const complex<_Tp>& __z) - { - _Tp __x = __z.real(); - _Tp __y = __z.imag(); - const _Tp __s = std::max(abs(__x), abs(__y)); - if (__s == _Tp()) // well ... - return __s; - __x /= __s; - __y /= __s; - return __s * sqrt(__x * __x + __y * __y); - } - #if _GLIBCXX_USE_C99_COMPLEX - inline float - __complex_abs(__complex__ float __z) { return __builtin_cabsf(__z); } +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline _Float16 + __complex_abs(__complex__ _Float16 __z) + { return _Float16(__builtin_cabsf(__z)); } - inline double - __complex_abs(__complex__ double __z) { return __builtin_cabs(__z); } + inline _Float16 + __complex_arg(__complex__ _Float16 __z) + { return _Float16(__builtin_cargf(__z)); } - inline long double - __complex_abs(const __complex__ long double& __z) - { return __builtin_cabsl(__z); } + inline __complex__ _Float16 + __complex_cos(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ccosf(__z)); } - template - inline _Tp - abs(const complex<_Tp>& __z) { return __complex_abs(__z.__rep()); } -#else - template - inline _Tp - abs(const complex<_Tp>& __z) { return __complex_abs(__z); } -#endif + inline __complex__ _Float16 + __complex_cosh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ccoshf(__z)); } + inline __complex__ _Float16 + __complex_exp(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cexpf(__z)); } - // 26.2.7/4: arg(__z): Returns the phase angle of __z. - template - inline _Tp - __complex_arg(const complex<_Tp>& __z) - { return atan2(__z.imag(), __z.real()); } + inline __complex__ _Float16 + __complex_log(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_clogf(__z)); } -#if _GLIBCXX_USE_C99_COMPLEX - inline float - __complex_arg(__complex__ float __z) { return __builtin_cargf(__z); } + inline __complex__ _Float16 + __complex_sin(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_csinf(__z)); } - inline double - __complex_arg(__complex__ double __z) { return __builtin_carg(__z); } + inline __complex__ _Float16 + __complex_sinh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_csinhf(__z)); } - inline long double - __complex_arg(const __complex__ long double& __z) - { return __builtin_cargl(__z); } + inline __complex__ _Float16 + __complex_sqrt(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_csqrtf(__z)); } - template - inline _Tp - arg(const complex<_Tp>& __z) { return __complex_arg(__z.__rep()); } -#else - template - inline _Tp - arg(const complex<_Tp>& __z) { return __complex_arg(__z); } + inline __complex__ _Float16 + __complex_tan(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ctanf(__z)); } + + inline __complex__ _Float16 + __complex_tanh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ctanhf(__z)); } + + inline __complex__ _Float16 + __complex_pow(__complex__ _Float16 __x, __complex__ _Float16 __y) + { return static_cast<__complex__ _Float16>(__builtin_cpowf(__x, __y)); } #endif - // 26.2.7/5: norm(__z) returns the squared magnitude of __z. - // As defined, norm() is -not- a norm is the common mathematical - // sense used in numerics. The helper class _Norm_helper<> tries to - // distinguish between builtin floating point and the rest, so as - // to deliver an answer as close as possible to the real value. - template - struct _Norm_helper - { - template - static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return __x * __x + __y * __y; - } - }; +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline _Float32 + __complex_abs(__complex__ _Float32 __z) { return __builtin_cabsf(__z); } - template<> - struct _Norm_helper - { - template - static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) - { - //_Tp __res = std::abs(__z); - //return __res * __res; - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return __x * __x + __y * __y; - } - }; + inline _Float32 + __complex_arg(__complex__ _Float32 __z) { return __builtin_cargf(__z); } - template - inline _GLIBCXX20_CONSTEXPR _Tp - norm(const complex<_Tp>& __z) - { - return _Norm_helper<__is_floating<_Tp>::__value - && !_GLIBCXX_FAST_MATH>::_S_do_it(__z); - } + inline __complex__ _Float32 + __complex_cos(__complex__ _Float32 __z) { return __builtin_ccosf(__z); } - template - inline complex<_Tp> - polar(const _Tp& __rho, const _Tp& __theta) - { - __glibcxx_assert( __rho >= 0 ); - return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta)); - } + inline __complex__ _Float32 + __complex_cosh(__complex__ _Float32 __z) { return __builtin_ccoshf(__z); } - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - conj(const complex<_Tp>& __z) - { return complex<_Tp>(__z.real(), -__z.imag()); } + inline __complex__ _Float32 + __complex_exp(__complex__ _Float32 __z) { return __builtin_cexpf(__z); } - // Transcendentals + inline __complex__ _Float32 + __complex_log(__complex__ _Float32 __z) { return __builtin_clogf(__z); } - // 26.2.8/1 cos(__z): Returns the cosine of __z. - template - inline complex<_Tp> - __complex_cos(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(cos(__x) * cosh(__y), -sin(__x) * sinh(__y)); - } + inline __complex__ _Float32 + __complex_sin(__complex__ _Float32 __z) { return __builtin_csinf(__z); } -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_cos(__complex__ float __z) { return __builtin_ccosf(__z); } + inline __complex__ _Float32 + __complex_sinh(__complex__ _Float32 __z) { return __builtin_csinhf(__z); } - inline __complex__ double - __complex_cos(__complex__ double __z) { return __builtin_ccos(__z); } + inline __complex__ _Float32 + __complex_sqrt(__complex__ _Float32 __z) { return __builtin_csqrtf(__z); } - inline __complex__ long double - __complex_cos(const __complex__ long double& __z) - { return __builtin_ccosl(__z); } + inline __complex__ _Float32 + __complex_tan(__complex__ _Float32 __z) { return __builtin_ctanf(__z); } - template - inline complex<_Tp> - cos(const complex<_Tp>& __z) { return __complex_cos(__z.__rep()); } -#else - template - inline complex<_Tp> - cos(const complex<_Tp>& __z) { return __complex_cos(__z); } + inline __complex__ _Float32 + __complex_tanh(__complex__ _Float32 __z) { return __builtin_ctanhf(__z); } + + inline __complex__ _Float32 + __complex_pow(__complex__ _Float32 __x, __complex__ _Float32 __y) + { return __builtin_cpowf(__x, __y); } #endif - // 26.2.8/2 cosh(__z): Returns the hyperbolic cosine of __z. - template - inline complex<_Tp> - __complex_cosh(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(cosh(__x) * cos(__y), sinh(__x) * sin(__y)); - } +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline _Float64 + __complex_abs(__complex__ _Float64 __z) { return __builtin_cabs(__z); } -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_cosh(__complex__ float __z) { return __builtin_ccoshf(__z); } + inline _Float64 + __complex_arg(__complex__ _Float64 __z) { return __builtin_carg(__z); } - inline __complex__ double - __complex_cosh(__complex__ double __z) { return __builtin_ccosh(__z); } + inline __complex__ _Float64 + __complex_cos(__complex__ _Float64 __z) { return __builtin_ccos(__z); } - inline __complex__ long double - __complex_cosh(const __complex__ long double& __z) - { return __builtin_ccoshl(__z); } + inline __complex__ _Float64 + __complex_cosh(__complex__ _Float64 __z) { return __builtin_ccosh(__z); } - template - inline complex<_Tp> - cosh(const complex<_Tp>& __z) { return __complex_cosh(__z.__rep()); } -#else - template - inline complex<_Tp> - cosh(const complex<_Tp>& __z) { return __complex_cosh(__z); } + inline __complex__ _Float64 + __complex_exp(__complex__ _Float64 __z) { return __builtin_cexp(__z); } + + inline __complex__ _Float64 + __complex_log(__complex__ _Float64 __z) { return __builtin_clog(__z); } + + inline __complex__ _Float64 + __complex_sin(__complex__ _Float64 __z) { return __builtin_csin(__z); } + + inline __complex__ _Float64 + __complex_sinh(__complex__ _Float64 __z) { return __builtin_csinh(__z); } + + inline __complex__ _Float64 + __complex_sqrt(__complex__ _Float64 __z) { return __builtin_csqrt(__z); } + + inline __complex__ _Float64 + __complex_tan(__complex__ _Float64 __z) { return __builtin_ctan(__z); } + + inline __complex__ _Float64 + __complex_tanh(__complex__ _Float64 __z) { return __builtin_ctanh(__z); } + + inline __complex__ _Float64 + __complex_pow(__complex__ _Float64 __x, __complex__ _Float64 __y) + { return __builtin_cpow(__x, __y); } #endif - // 26.2.8/3 exp(__z): Returns the complex base e exponential of x - template - inline complex<_Tp> - __complex_exp(const complex<_Tp>& __z) - { return std::polar<_Tp>(exp(__z.real()), __z.imag()); } +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline _Float128 + __complex_abs(__complex__ _Float128 __z) { return __builtin_cabsl(__z); } + + inline _Float128 + __complex_arg(__complex__ _Float128 __z) { return __builtin_cargl(__z); } + + inline __complex__ _Float128 + __complex_cos(__complex__ _Float128 __z) { return __builtin_ccosl(__z); } + + inline __complex__ _Float128 + __complex_cosh(__complex__ _Float128 __z) { return __builtin_ccoshl(__z); } + + inline __complex__ _Float128 + __complex_exp(__complex__ _Float128 __z) { return __builtin_cexpl(__z); } + + inline __complex__ _Float128 + __complex_log(__complex__ _Float128 __z) { return __builtin_clogl(__z); } + + inline __complex__ _Float128 + __complex_sin(__complex__ _Float128 __z) { return __builtin_csinl(__z); } + + inline __complex__ _Float128 + __complex_sinh(__complex__ _Float128 __z) { return __builtin_csinhl(__z); } -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_exp(__complex__ float __z) { return __builtin_cexpf(__z); } + inline __complex__ _Float128 + __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtl(__z); } - inline __complex__ double - __complex_exp(__complex__ double __z) { return __builtin_cexp(__z); } + inline __complex__ _Float128 + __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanl(__z); } - inline __complex__ long double - __complex_exp(const __complex__ long double& __z) - { return __builtin_cexpl(__z); } + inline __complex__ _Float128 + __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhl(__z); } - template - inline complex<_Tp> - exp(const complex<_Tp>& __z) { return __complex_exp(__z.__rep()); } -#else - template - inline complex<_Tp> - exp(const complex<_Tp>& __z) { return __complex_exp(__z); } -#endif + inline __complex__ _Float128 + __complex_pow(__complex__ _Float128 __x, __complex__ _Float128 __y) + { return __builtin_cpowl(__x, __y); } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) + inline _Float128 + __complex_abs(__complex__ _Float128 __z) { return __builtin_cabsf128(__z); } - // 26.2.8/5 log(__z): Returns the natural complex logarithm of __z. - // The branch cut is along the negative axis. - template - inline complex<_Tp> - __complex_log(const complex<_Tp>& __z) - { return complex<_Tp>(log(std::abs(__z)), std::arg(__z)); } + inline _Float128 + __complex_arg(__complex__ _Float128 __z) { return __builtin_cargf128(__z); } -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_log(__complex__ float __z) { return __builtin_clogf(__z); } + inline __complex__ _Float128 + __complex_cos(__complex__ _Float128 __z) { return __builtin_ccosf128(__z); } - inline __complex__ double - __complex_log(__complex__ double __z) { return __builtin_clog(__z); } + inline __complex__ _Float128 + __complex_cosh(__complex__ _Float128 __z) { return __builtin_ccoshf128(__z); } - inline __complex__ long double - __complex_log(const __complex__ long double& __z) - { return __builtin_clogl(__z); } + inline __complex__ _Float128 + __complex_exp(__complex__ _Float128 __z) { return __builtin_cexpf128(__z); } - template - inline complex<_Tp> - log(const complex<_Tp>& __z) { return __complex_log(__z.__rep()); } -#else - template - inline complex<_Tp> - log(const complex<_Tp>& __z) { return __complex_log(__z); } -#endif + inline __complex__ _Float128 + __complex_log(__complex__ _Float128 __z) { return __builtin_clogf128(__z); } - template - inline complex<_Tp> - log10(const complex<_Tp>& __z) - { return std::log(__z) / log(_Tp(10.0)); } + inline __complex__ _Float128 + __complex_sin(__complex__ _Float128 __z) { return __builtin_csinf128(__z); } - // 26.2.8/10 sin(__z): Returns the sine of __z. - template - inline complex<_Tp> - __complex_sin(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(sin(__x) * cosh(__y), cos(__x) * sinh(__y)); - } + inline __complex__ _Float128 + __complex_sinh(__complex__ _Float128 __z) { return __builtin_csinhf128(__z); } -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_sin(__complex__ float __z) { return __builtin_csinf(__z); } + inline __complex__ _Float128 + __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtf128(__z); } - inline __complex__ double - __complex_sin(__complex__ double __z) { return __builtin_csin(__z); } + inline __complex__ _Float128 + __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanf128(__z); } - inline __complex__ long double - __complex_sin(const __complex__ long double& __z) - { return __builtin_csinl(__z); } + inline __complex__ _Float128 + __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhf128(__z); } - template - inline complex<_Tp> - sin(const complex<_Tp>& __z) { return __complex_sin(__z.__rep()); } -#else - template - inline complex<_Tp> - sin(const complex<_Tp>& __z) { return __complex_sin(__z); } + inline __complex__ _Float128 + __complex_pow(__complex__ _Float128 __x, __complex__ _Float128 __y) + { return __builtin_cpowf128(__x, __y); } #endif - // 26.2.8/11 sinh(__z): Returns the hyperbolic sine of __z. - template - inline complex<_Tp> - __complex_sinh(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(sinh(__x) * cos(__y), cosh(__x) * sin(__y)); - } +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __gnu_cxx::__bfloat16_t + __complex_abs(__complex__ decltype(0.0bf16) __z) + { return __gnu_cxx::__bfloat16_t(__builtin_cabsf(__z)); } -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_sinh(__complex__ float __z) { return __builtin_csinhf(__z); } + inline __gnu_cxx::__bfloat16_t + __complex_arg(__complex__ decltype(0.0bf16) __z) + { return __gnu_cxx::__bfloat16_t(__builtin_cargf(__z)); } - inline __complex__ double - __complex_sinh(__complex__ double __z) { return __builtin_csinh(__z); } + inline __complex__ decltype(0.0bf16) + __complex_cos(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccosf(__z)); } - inline __complex__ long double - __complex_sinh(const __complex__ long double& __z) - { return __builtin_csinhl(__z); } + inline __complex__ decltype(0.0bf16) + __complex_cosh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccoshf(__z)); } - template - inline complex<_Tp> - sinh(const complex<_Tp>& __z) { return __complex_sinh(__z.__rep()); } -#else - template - inline complex<_Tp> - sinh(const complex<_Tp>& __z) { return __complex_sinh(__z); } -#endif + inline __complex__ decltype(0.0bf16) + __complex_exp(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cexpf(__z)); } - // 26.2.8/13 sqrt(__z): Returns the complex square root of __z. - // The branch cut is on the negative axis. - template - complex<_Tp> - __complex_sqrt(const complex<_Tp>& __z) - { - _Tp __x = __z.real(); - _Tp __y = __z.imag(); + inline __complex__ decltype(0.0bf16) + __complex_log(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_clogf(__z)); } - if (__x == _Tp()) - { - _Tp __t = sqrt(abs(__y) / 2); - return complex<_Tp>(__t, __y < _Tp() ? -__t : __t); - } - else - { - _Tp __t = sqrt(2 * (std::abs(__z) + abs(__x))); - _Tp __u = __t / 2; - return __x > _Tp() - ? complex<_Tp>(__u, __y / __t) - : complex<_Tp>(abs(__y) / __t, __y < _Tp() ? -__u : __u); - } - } + inline __complex__ decltype(0.0bf16) + __complex_sin(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csinf(__z)); } -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_sqrt(__complex__ float __z) { return __builtin_csqrtf(__z); } + inline __complex__ decltype(0.0bf16) + __complex_sinh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csinhf(__z)); } - inline __complex__ double - __complex_sqrt(__complex__ double __z) { return __builtin_csqrt(__z); } + inline __complex__ decltype(0.0bf16) + __complex_sqrt(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csqrtf(__z)); } - inline __complex__ long double - __complex_sqrt(const __complex__ long double& __z) - { return __builtin_csqrtl(__z); } + inline __complex__ decltype(0.0bf16) + __complex_tan(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanf(__z)); } - template - inline complex<_Tp> - sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z.__rep()); } -#else - template - inline complex<_Tp> - sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z); } -#endif + inline __complex__ decltype(0.0bf16) + __complex_tanh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanhf(__z)); } - // 26.2.8/14 tan(__z): Return the complex tangent of __z. + inline __complex__ decltype(0.0bf16) + __complex_pow(__complex__ decltype(0.0bf16) __x, + __complex__ decltype(0.0bf16) __y) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cpowf(__x, + __y)); } +#endif +#endif + // 26.2.7/3 abs(__z): Returns the magnitude of __z. template - inline complex<_Tp> - __complex_tan(const complex<_Tp>& __z) - { return std::sin(__z) / std::cos(__z); } + inline _Tp + __complex_abs(const complex<_Tp>& __z) + { + _Tp __x = __z.real(); + _Tp __y = __z.imag(); + const _Tp __s = std::max(abs(__x), abs(__y)); + if (__s == _Tp()) // well ... + return __s; + __x /= __s; + __y /= __s; + return __s * sqrt(__x * __x + __y * __y); + } #if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_tan(__complex__ float __z) { return __builtin_ctanf(__z); } + inline float + __complex_abs(__complex__ float __z) { return __builtin_cabsf(__z); } - inline __complex__ double - __complex_tan(__complex__ double __z) { return __builtin_ctan(__z); } + inline double + __complex_abs(__complex__ double __z) { return __builtin_cabs(__z); } - inline __complex__ long double - __complex_tan(const __complex__ long double& __z) - { return __builtin_ctanl(__z); } + inline long double + __complex_abs(const __complex__ long double& __z) + { return __builtin_cabsl(__z); } template - inline complex<_Tp> - tan(const complex<_Tp>& __z) { return __complex_tan(__z.__rep()); } + inline _Tp + abs(const complex<_Tp>& __z) { return __complex_abs(__z.__rep()); } #else template - inline complex<_Tp> - tan(const complex<_Tp>& __z) { return __complex_tan(__z); } + inline _Tp + abs(const complex<_Tp>& __z) { return __complex_abs(__z); } #endif - // 26.2.8/15 tanh(__z): Returns the hyperbolic tangent of __z. - + // 26.2.7/4: arg(__z): Returns the phase angle of __z. template - inline complex<_Tp> - __complex_tanh(const complex<_Tp>& __z) - { return std::sinh(__z) / std::cosh(__z); } + inline _Tp + __complex_arg(const complex<_Tp>& __z) + { return atan2(__z.imag(), __z.real()); } #if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_tanh(__complex__ float __z) { return __builtin_ctanhf(__z); } + inline float + __complex_arg(__complex__ float __z) { return __builtin_cargf(__z); } - inline __complex__ double - __complex_tanh(__complex__ double __z) { return __builtin_ctanh(__z); } + inline double + __complex_arg(__complex__ double __z) { return __builtin_carg(__z); } - inline __complex__ long double - __complex_tanh(const __complex__ long double& __z) - { return __builtin_ctanhl(__z); } + inline long double + __complex_arg(const __complex__ long double& __z) + { return __builtin_cargl(__z); } template - inline complex<_Tp> - tanh(const complex<_Tp>& __z) { return __complex_tanh(__z.__rep()); } + inline _Tp + arg(const complex<_Tp>& __z) { return __complex_arg(__z.__rep()); } #else template - inline complex<_Tp> - tanh(const complex<_Tp>& __z) { return __complex_tanh(__z); } + inline _Tp + arg(const complex<_Tp>& __z) { return __complex_arg(__z); } #endif - - // 26.2.8/9 pow(__x, __y): Returns the complex power base of __x - // raised to the __y-th power. The branch - // cut is on the negative axis. - template - complex<_Tp> - __complex_pow_unsigned(complex<_Tp> __x, unsigned __n) + // 26.2.7/5: norm(__z) returns the squared magnitude of __z. + // As defined, norm() is -not- a norm is the common mathematical + // sense used in numerics. The helper class _Norm_helper<> tries to + // distinguish between builtin floating point and the rest, so as + // to deliver an answer as close as possible to the real value. + template + struct _Norm_helper { - complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(1); + template + static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return __x * __x + __y * __y; + } + }; - while (__n >>= 1) + template<> + struct _Norm_helper + { + template + static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) { - __x *= __x; - if (__n % 2) - __y *= __x; + //_Tp __res = std::abs(__z); + //return __res * __res; + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return __x * __x + __y * __y; } + }; - return __y; + template + inline _GLIBCXX20_CONSTEXPR _Tp + norm(const complex<_Tp>& __z) + { + return _Norm_helper<__is_floating<_Tp>::__value + && !_GLIBCXX_FAST_MATH>::_S_do_it(__z); } - // In C++11 mode we used to implement the resolution of - // DR 844. complex pow return type is ambiguous. - // thus the following overload was disabled in that mode. However, doing - // that causes all sorts of issues, see, for example: - // http://gcc.gnu.org/ml/libstdc++/2013-01/msg00058.html - // and also PR57974. template inline complex<_Tp> - pow(const complex<_Tp>& __z, int __n) + polar(const _Tp& __rho, const _Tp& __theta) { - return __n < 0 - ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -(unsigned)__n) - : std::__complex_pow_unsigned(__z, __n); + __glibcxx_assert( __rho >= 0 ); + return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta)); } template - complex<_Tp> - pow(const complex<_Tp>& __x, const _Tp& __y) - { -#if ! _GLIBCXX_USE_C99_COMPLEX - if (__x == _Tp()) - return _Tp(); -#endif - if (__x.imag() == _Tp() && __x.real() > _Tp()) - return pow(__x.real(), __y); + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + conj(const complex<_Tp>& __z) + { return complex<_Tp>(__z.real(), -__z.imag()); } - complex<_Tp> __t = std::log(__x); - return std::polar<_Tp>(exp(__y * __t.real()), __y * __t.imag()); - } + // Transcendentals + // 26.2.8/1 cos(__z): Returns the cosine of __z. template inline complex<_Tp> - __complex_pow(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __x == _Tp() ? _Tp() : std::exp(__y * std::log(__x)); } + __complex_cos(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(cos(__x) * cosh(__y), -sin(__x) * sinh(__y)); + } #if _GLIBCXX_USE_C99_COMPLEX inline __complex__ float - __complex_pow(__complex__ float __x, __complex__ float __y) - { return __builtin_cpowf(__x, __y); } + __complex_cos(__complex__ float __z) { return __builtin_ccosf(__z); } inline __complex__ double - __complex_pow(__complex__ double __x, __complex__ double __y) - { return __builtin_cpow(__x, __y); } + __complex_cos(__complex__ double __z) { return __builtin_ccos(__z); } inline __complex__ long double - __complex_pow(const __complex__ long double& __x, - const __complex__ long double& __y) - { return __builtin_cpowl(__x, __y); } + __complex_cos(const __complex__ long double& __z) + { return __builtin_ccosl(__z); } template inline complex<_Tp> - pow(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __complex_pow(__x.__rep(), __y.__rep()); } + cos(const complex<_Tp>& __z) { return __complex_cos(__z.__rep()); } #else template inline complex<_Tp> - pow(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __complex_pow(__x, __y); } + cos(const complex<_Tp>& __z) { return __complex_cos(__z); } #endif + // 26.2.8/2 cosh(__z): Returns the hyperbolic cosine of __z. template inline complex<_Tp> - pow(const _Tp& __x, const complex<_Tp>& __y) + __complex_cosh(const complex<_Tp>& __z) { - return __x > _Tp() ? std::polar<_Tp>(pow(__x, __y.real()), - __y.imag() * log(__x)) - : std::pow(complex<_Tp>(__x), __y); + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(cosh(__x) * cos(__y), sinh(__x) * sin(__y)); } #if _GLIBCXX_USE_C99_COMPLEX -#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - inline _Float16 - __complex_abs(__complex__ _Float16 __z) - { return _Float16(__builtin_cabsf(__z)); } - - inline _Float16 - __complex_arg(__complex__ _Float16 __z) - { return _Float16(__builtin_cargf(__z)); } - - inline __complex__ _Float16 - __complex_cos(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_ccosf(__z)); } - - inline __complex__ _Float16 - __complex_cosh(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_ccoshf(__z)); } - - inline __complex__ _Float16 - __complex_exp(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_cexpf(__z)); } - - inline __complex__ _Float16 - __complex_log(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_clogf(__z)); } - - inline __complex__ _Float16 - __complex_sin(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_csinf(__z)); } - - inline __complex__ _Float16 - __complex_sinh(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_csinhf(__z)); } - - inline __complex__ _Float16 - __complex_sqrt(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_csqrtf(__z)); } + inline __complex__ float + __complex_cosh(__complex__ float __z) { return __builtin_ccoshf(__z); } - inline __complex__ _Float16 - __complex_tan(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_ctanf(__z)); } + inline __complex__ double + __complex_cosh(__complex__ double __z) { return __builtin_ccosh(__z); } - inline __complex__ _Float16 - __complex_tanh(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_ctanhf(__z)); } + inline __complex__ long double + __complex_cosh(const __complex__ long double& __z) + { return __builtin_ccoshl(__z); } - inline __complex__ _Float16 - __complex_pow(__complex__ _Float16 __x, __complex__ _Float16 __y) - { return static_cast<__complex__ _Float16>(__builtin_cpowf(__x, __y)); } + template + inline complex<_Tp> + cosh(const complex<_Tp>& __z) { return __complex_cosh(__z.__rep()); } +#else + template + inline complex<_Tp> + cosh(const complex<_Tp>& __z) { return __complex_cosh(__z); } #endif -#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - inline _Float32 - __complex_abs(__complex__ _Float32 __z) { return __builtin_cabsf(__z); } - - inline _Float32 - __complex_arg(__complex__ _Float32 __z) { return __builtin_cargf(__z); } - - inline __complex__ _Float32 - __complex_cos(__complex__ _Float32 __z) { return __builtin_ccosf(__z); } - - inline __complex__ _Float32 - __complex_cosh(__complex__ _Float32 __z) { return __builtin_ccoshf(__z); } - - inline __complex__ _Float32 - __complex_exp(__complex__ _Float32 __z) { return __builtin_cexpf(__z); } - - inline __complex__ _Float32 - __complex_log(__complex__ _Float32 __z) { return __builtin_clogf(__z); } - - inline __complex__ _Float32 - __complex_sin(__complex__ _Float32 __z) { return __builtin_csinf(__z); } - - inline __complex__ _Float32 - __complex_sinh(__complex__ _Float32 __z) { return __builtin_csinhf(__z); } + // 26.2.8/3 exp(__z): Returns the complex base e exponential of x + template + inline complex<_Tp> + __complex_exp(const complex<_Tp>& __z) + { return std::polar<_Tp>(exp(__z.real()), __z.imag()); } - inline __complex__ _Float32 - __complex_sqrt(__complex__ _Float32 __z) { return __builtin_csqrtf(__z); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_exp(__complex__ float __z) { return __builtin_cexpf(__z); } - inline __complex__ _Float32 - __complex_tan(__complex__ _Float32 __z) { return __builtin_ctanf(__z); } + inline __complex__ double + __complex_exp(__complex__ double __z) { return __builtin_cexp(__z); } - inline __complex__ _Float32 - __complex_tanh(__complex__ _Float32 __z) { return __builtin_ctanhf(__z); } + inline __complex__ long double + __complex_exp(const __complex__ long double& __z) + { return __builtin_cexpl(__z); } - inline __complex__ _Float32 - __complex_pow(__complex__ _Float32 __x, __complex__ _Float32 __y) - { return __builtin_cpowf(__x, __y); } + template + inline complex<_Tp> + exp(const complex<_Tp>& __z) { return __complex_exp(__z.__rep()); } +#else + template + inline complex<_Tp> + exp(const complex<_Tp>& __z) { return __complex_exp(__z); } #endif -#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) - inline _Float64 - __complex_abs(__complex__ _Float64 __z) { return __builtin_cabs(__z); } - - inline _Float64 - __complex_arg(__complex__ _Float64 __z) { return __builtin_carg(__z); } + // 26.2.8/5 log(__z): Returns the natural complex logarithm of __z. + // The branch cut is along the negative axis. + template + inline complex<_Tp> + __complex_log(const complex<_Tp>& __z) + { return complex<_Tp>(log(std::abs(__z)), std::arg(__z)); } - inline __complex__ _Float64 - __complex_cos(__complex__ _Float64 __z) { return __builtin_ccos(__z); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_log(__complex__ float __z) { return __builtin_clogf(__z); } - inline __complex__ _Float64 - __complex_cosh(__complex__ _Float64 __z) { return __builtin_ccosh(__z); } + inline __complex__ double + __complex_log(__complex__ double __z) { return __builtin_clog(__z); } - inline __complex__ _Float64 - __complex_exp(__complex__ _Float64 __z) { return __builtin_cexp(__z); } + inline __complex__ long double + __complex_log(const __complex__ long double& __z) + { return __builtin_clogl(__z); } - inline __complex__ _Float64 - __complex_log(__complex__ _Float64 __z) { return __builtin_clog(__z); } + template + inline complex<_Tp> + log(const complex<_Tp>& __z) { return __complex_log(__z.__rep()); } +#else + template + inline complex<_Tp> + log(const complex<_Tp>& __z) { return __complex_log(__z); } +#endif - inline __complex__ _Float64 - __complex_sin(__complex__ _Float64 __z) { return __builtin_csin(__z); } + template + inline complex<_Tp> + log10(const complex<_Tp>& __z) + { return std::log(__z) / log(_Tp(10.0)); } - inline __complex__ _Float64 - __complex_sinh(__complex__ _Float64 __z) { return __builtin_csinh(__z); } + // 26.2.8/10 sin(__z): Returns the sine of __z. + template + inline complex<_Tp> + __complex_sin(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(sin(__x) * cosh(__y), cos(__x) * sinh(__y)); + } - inline __complex__ _Float64 - __complex_sqrt(__complex__ _Float64 __z) { return __builtin_csqrt(__z); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sin(__complex__ float __z) { return __builtin_csinf(__z); } - inline __complex__ _Float64 - __complex_tan(__complex__ _Float64 __z) { return __builtin_ctan(__z); } + inline __complex__ double + __complex_sin(__complex__ double __z) { return __builtin_csin(__z); } - inline __complex__ _Float64 - __complex_tanh(__complex__ _Float64 __z) { return __builtin_ctanh(__z); } + inline __complex__ long double + __complex_sin(const __complex__ long double& __z) + { return __builtin_csinl(__z); } - inline __complex__ _Float64 - __complex_pow(__complex__ _Float64 __x, __complex__ _Float64 __y) - { return __builtin_cpow(__x, __y); } + template + inline complex<_Tp> + sin(const complex<_Tp>& __z) { return __complex_sin(__z.__rep()); } +#else + template + inline complex<_Tp> + sin(const complex<_Tp>& __z) { return __complex_sin(__z); } #endif -#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) - inline _Float128 - __complex_abs(__complex__ _Float128 __z) { return __builtin_cabsl(__z); } + // 26.2.8/11 sinh(__z): Returns the hyperbolic sine of __z. + template + inline complex<_Tp> + __complex_sinh(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(sinh(__x) * cos(__y), cosh(__x) * sin(__y)); + } - inline _Float128 - __complex_arg(__complex__ _Float128 __z) { return __builtin_cargl(__z); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sinh(__complex__ float __z) { return __builtin_csinhf(__z); } - inline __complex__ _Float128 - __complex_cos(__complex__ _Float128 __z) { return __builtin_ccosl(__z); } + inline __complex__ double + __complex_sinh(__complex__ double __z) { return __builtin_csinh(__z); } - inline __complex__ _Float128 - __complex_cosh(__complex__ _Float128 __z) { return __builtin_ccoshl(__z); } + inline __complex__ long double + __complex_sinh(const __complex__ long double& __z) + { return __builtin_csinhl(__z); } - inline __complex__ _Float128 - __complex_exp(__complex__ _Float128 __z) { return __builtin_cexpl(__z); } + template + inline complex<_Tp> + sinh(const complex<_Tp>& __z) { return __complex_sinh(__z.__rep()); } +#else + template + inline complex<_Tp> + sinh(const complex<_Tp>& __z) { return __complex_sinh(__z); } +#endif - inline __complex__ _Float128 - __complex_log(__complex__ _Float128 __z) { return __builtin_clogl(__z); } + // 26.2.8/13 sqrt(__z): Returns the complex square root of __z. + // The branch cut is on the negative axis. + template + complex<_Tp> + __complex_sqrt(const complex<_Tp>& __z) + { + _Tp __x = __z.real(); + _Tp __y = __z.imag(); - inline __complex__ _Float128 - __complex_sin(__complex__ _Float128 __z) { return __builtin_csinl(__z); } + if (__x == _Tp()) + { + _Tp __t = sqrt(abs(__y) / 2); + return complex<_Tp>(__t, __y < _Tp() ? -__t : __t); + } + else + { + _Tp __t = sqrt(2 * (std::abs(__z) + abs(__x))); + _Tp __u = __t / 2; + return __x > _Tp() + ? complex<_Tp>(__u, __y / __t) + : complex<_Tp>(abs(__y) / __t, __y < _Tp() ? -__u : __u); + } + } - inline __complex__ _Float128 - __complex_sinh(__complex__ _Float128 __z) { return __builtin_csinhl(__z); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sqrt(__complex__ float __z) { return __builtin_csqrtf(__z); } - inline __complex__ _Float128 - __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtl(__z); } + inline __complex__ double + __complex_sqrt(__complex__ double __z) { return __builtin_csqrt(__z); } - inline __complex__ _Float128 - __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanl(__z); } + inline __complex__ long double + __complex_sqrt(const __complex__ long double& __z) + { return __builtin_csqrtl(__z); } - inline __complex__ _Float128 - __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhl(__z); } + template + inline complex<_Tp> + sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z.__rep()); } +#else + template + inline complex<_Tp> + sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z); } +#endif - inline __complex__ _Float128 - __complex_pow(__complex__ _Float128 __x, __complex__ _Float128 __y) - { return __builtin_cpowl(__x, __y); } -#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) - inline _Float128 - __complex_abs(__complex__ _Float128 __z) { return __builtin_cabsf128(__z); } + // 26.2.8/14 tan(__z): Return the complex tangent of __z. - inline _Float128 - __complex_arg(__complex__ _Float128 __z) { return __builtin_cargf128(__z); } + template + inline complex<_Tp> + __complex_tan(const complex<_Tp>& __z) + { return std::sin(__z) / std::cos(__z); } - inline __complex__ _Float128 - __complex_cos(__complex__ _Float128 __z) { return __builtin_ccosf128(__z); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_tan(__complex__ float __z) { return __builtin_ctanf(__z); } - inline __complex__ _Float128 - __complex_cosh(__complex__ _Float128 __z) { return __builtin_ccoshf128(__z); } + inline __complex__ double + __complex_tan(__complex__ double __z) { return __builtin_ctan(__z); } - inline __complex__ _Float128 - __complex_exp(__complex__ _Float128 __z) { return __builtin_cexpf128(__z); } + inline __complex__ long double + __complex_tan(const __complex__ long double& __z) + { return __builtin_ctanl(__z); } - inline __complex__ _Float128 - __complex_log(__complex__ _Float128 __z) { return __builtin_clogf128(__z); } + template + inline complex<_Tp> + tan(const complex<_Tp>& __z) { return __complex_tan(__z.__rep()); } +#else + template + inline complex<_Tp> + tan(const complex<_Tp>& __z) { return __complex_tan(__z); } +#endif - inline __complex__ _Float128 - __complex_sin(__complex__ _Float128 __z) { return __builtin_csinf128(__z); } - inline __complex__ _Float128 - __complex_sinh(__complex__ _Float128 __z) { return __builtin_csinhf128(__z); } + // 26.2.8/15 tanh(__z): Returns the hyperbolic tangent of __z. - inline __complex__ _Float128 - __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtf128(__z); } + template + inline complex<_Tp> + __complex_tanh(const complex<_Tp>& __z) + { return std::sinh(__z) / std::cosh(__z); } - inline __complex__ _Float128 - __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanf128(__z); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_tanh(__complex__ float __z) { return __builtin_ctanhf(__z); } - inline __complex__ _Float128 - __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhf128(__z); } + inline __complex__ double + __complex_tanh(__complex__ double __z) { return __builtin_ctanh(__z); } - inline __complex__ _Float128 - __complex_pow(__complex__ _Float128 __x, __complex__ _Float128 __y) - { return __builtin_cpowf128(__x, __y); } + inline __complex__ long double + __complex_tanh(const __complex__ long double& __z) + { return __builtin_ctanhl(__z); } + + template + inline complex<_Tp> + tanh(const complex<_Tp>& __z) { return __complex_tanh(__z.__rep()); } +#else + template + inline complex<_Tp> + tanh(const complex<_Tp>& __z) { return __complex_tanh(__z); } #endif -#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - inline __gnu_cxx::__bfloat16_t - __complex_abs(__complex__ decltype(0.0bf16) __z) - { return __gnu_cxx::__bfloat16_t(__builtin_cabsf(__z)); } - inline __gnu_cxx::__bfloat16_t - __complex_arg(__complex__ decltype(0.0bf16) __z) - { return __gnu_cxx::__bfloat16_t(__builtin_cargf(__z)); } + // 26.2.8/9 pow(__x, __y): Returns the complex power base of __x + // raised to the __y-th power. The branch + // cut is on the negative axis. + template + complex<_Tp> + __complex_pow_unsigned(complex<_Tp> __x, unsigned __n) + { + complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(1); - inline __complex__ decltype(0.0bf16) - __complex_cos(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccosf(__z)); } + while (__n >>= 1) + { + __x *= __x; + if (__n % 2) + __y *= __x; + } - inline __complex__ decltype(0.0bf16) - __complex_cosh(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccoshf(__z)); } + return __y; + } - inline __complex__ decltype(0.0bf16) - __complex_exp(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cexpf(__z)); } + // In C++11 mode we used to implement the resolution of + // DR 844. complex pow return type is ambiguous. + // thus the following overload was disabled in that mode. However, doing + // that causes all sorts of issues, see, for example: + // http://gcc.gnu.org/ml/libstdc++/2013-01/msg00058.html + // and also PR57974. + template + inline complex<_Tp> + pow(const complex<_Tp>& __z, int __n) + { + return __n < 0 + ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -(unsigned)__n) + : std::__complex_pow_unsigned(__z, __n); + } - inline __complex__ decltype(0.0bf16) - __complex_log(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_clogf(__z)); } + template + complex<_Tp> + pow(const complex<_Tp>& __x, const _Tp& __y) + { +#if ! _GLIBCXX_USE_C99_COMPLEX + if (__x == _Tp()) + return _Tp(); +#endif + if (__x.imag() == _Tp() && __x.real() > _Tp()) + return pow(__x.real(), __y); - inline __complex__ decltype(0.0bf16) - __complex_sin(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csinf(__z)); } + complex<_Tp> __t = std::log(__x); + return std::polar<_Tp>(exp(__y * __t.real()), __y * __t.imag()); + } - inline __complex__ decltype(0.0bf16) - __complex_sinh(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csinhf(__z)); } + template + inline complex<_Tp> + __complex_pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __x == _Tp() ? _Tp() : std::exp(__y * std::log(__x)); } - inline __complex__ decltype(0.0bf16) - __complex_sqrt(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csqrtf(__z)); } +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_pow(__complex__ float __x, __complex__ float __y) + { return __builtin_cpowf(__x, __y); } - inline __complex__ decltype(0.0bf16) - __complex_tan(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanf(__z)); } + inline __complex__ double + __complex_pow(__complex__ double __x, __complex__ double __y) + { return __builtin_cpow(__x, __y); } - inline __complex__ decltype(0.0bf16) - __complex_tanh(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanhf(__z)); } + inline __complex__ long double + __complex_pow(const __complex__ long double& __x, + const __complex__ long double& __y) + { return __builtin_cpowl(__x, __y); } - inline __complex__ decltype(0.0bf16) - __complex_pow(__complex__ decltype(0.0bf16) __x, - __complex__ decltype(0.0bf16) __y) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cpowf(__x, - __y)); } -#endif + template + inline complex<_Tp> + pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __complex_pow(__x.__rep(), __y.__rep()); } +#else + template + inline complex<_Tp> + pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __complex_pow(__x, __y); } #endif + template + inline complex<_Tp> + pow(const _Tp& __x, const complex<_Tp>& __y) + { + return __x > _Tp() ? std::polar<_Tp>(pow(__x, __y.real()), + __y.imag() * log(__x)) + : std::pow(complex<_Tp>(__x), __y); + } + /// 26.2.3 complex specializations /// complex specialization template<> @@ -1835,7 +1835,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template - requires(__complex_type<_Tp>::type) + requires requires { typename __complex_type<_Tp>::type; } class complex<_Tp> { public: @@ -1953,73 +1953,229 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #endif -#if __cplusplus <= 202002L - // These bits have to be at the end of this file, so that the - // specializations have all been defined. - inline _GLIBCXX_CONSTEXPR - complex::complex(const complex& __z) - : _M_value(__z.__rep()) { } +#if __cplusplus <= 202002L + // These bits have to be at the end of this file, so that the + // specializations have all been defined. + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } +#endif + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. +#if _GLIBCXX_EXTERN_TEMPLATE + extern template istream& operator>>(istream&, complex&); + extern template ostream& operator<<(ostream&, const complex&); + extern template istream& operator>>(istream&, complex&); + extern template ostream& operator<<(ostream&, const complex&); + extern template istream& operator>>(istream&, complex&); + extern template ostream& operator<<(ostream&, const complex&); + +#ifdef _GLIBCXX_USE_WCHAR_T + extern template wistream& operator>>(wistream&, complex&); + extern template wostream& operator<<(wostream&, const complex&); + extern template wistream& operator>>(wistream&, complex&); + extern template wostream& operator<<(wostream&, const complex&); + extern template wistream& operator>>(wistream&, complex&); + extern template wostream& operator<<(wostream&, const complex&); +#endif +#endif + + /// @} group complex_numbers + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Forward declarations. + template std::complex<_Tp> acos(const std::complex<_Tp>&); + template std::complex<_Tp> asin(const std::complex<_Tp>&); + template std::complex<_Tp> atan(const std::complex<_Tp>&); + + template std::complex<_Tp> acosh(const std::complex<_Tp>&); + template std::complex<_Tp> asinh(const std::complex<_Tp>&); + template std::complex<_Tp> atanh(const std::complex<_Tp>&); + // DR 595. + template _Tp fabs(const std::complex<_Tp>&); + + template + inline std::complex<_Tp> + __complex_acos(const std::complex<_Tp>& __z) + { + const std::complex<_Tp> __t = std::asin(__z); + const _Tp __pi_2 = 1.5707963267948966192313216916397514L; + return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag()); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float16 + __complex_acos(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cacosf(__z)); } + + inline __complex__ _Float16 + __complex_asin(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_casinf(__z)); } + + inline __complex__ _Float16 + __complex_atan(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_catanf(__z)); } + + inline __complex__ _Float16 + __complex_acosh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cacoshf(__z)); } + + inline __complex__ _Float16 + __complex_asinh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_casinhf(__z)); } + + inline __complex__ _Float16 + __complex_atanh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_catanhf(__z)); } +#endif + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float32 + __complex_acos(__complex__ _Float32 __z) + { return __builtin_cacosf(__z); } + + inline __complex__ _Float32 + __complex_asin(__complex__ _Float32 __z) + { return __builtin_casinf(__z); } + + inline __complex__ _Float32 + __complex_atan(__complex__ _Float32 __z) + { return __builtin_catanf(__z); } + + inline __complex__ _Float32 + __complex_acosh(__complex__ _Float32 __z) + { return __builtin_cacoshf(__z); } + + inline __complex__ _Float32 + __complex_asinh(__complex__ _Float32 __z) + { return __builtin_casinhf(__z); } + + inline __complex__ _Float32 + __complex_atanh(__complex__ _Float32 __z) + { return __builtin_catanhf(__z); } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline __complex__ _Float64 + __complex_acos(__complex__ _Float64 __z) + { return __builtin_cacos(__z); } + + inline __complex__ _Float64 + __complex_asin(__complex__ _Float64 __z) + { return __builtin_casin(__z); } + + inline __complex__ _Float64 + __complex_atan(__complex__ _Float64 __z) + { return __builtin_catan(__z); } + + inline __complex__ _Float64 + __complex_acosh(__complex__ _Float64 __z) + { return __builtin_cacosh(__z); } + + inline __complex__ _Float64 + __complex_asinh(__complex__ _Float64 __z) + { return __builtin_casinh(__z); } + + inline __complex__ _Float64 + __complex_atanh(__complex__ _Float64 __z) + { return __builtin_catanh(__z); } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline __complex__ _Float128 + __complex_acos(__complex__ _Float128 __z) + { return __builtin_cacosl(__z); } + + inline __complex__ _Float128 + __complex_asin(__complex__ _Float128 __z) + { return __builtin_casinl(__z); } + + inline __complex__ _Float128 + __complex_atan(__complex__ _Float128 __z) + { return __builtin_catanl(__z); } + + inline __complex__ _Float128 + __complex_acosh(__complex__ _Float128 __z) + { return __builtin_cacoshl(__z); } + + inline __complex__ _Float128 + __complex_asinh(__complex__ _Float128 __z) + { return __builtin_casinhl(__z); } + + inline __complex__ _Float128 + __complex_atanh(__complex__ _Float128 __z) + { return __builtin_catanhl(__z); } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) + inline __complex__ _Float128 + __complex_acos(__complex__ _Float128 __z) + { return __builtin_cacosf128(__z); } - inline _GLIBCXX_CONSTEXPR - complex::complex(const complex& __z) - : _M_value(__z.__rep()) { } + inline __complex__ _Float128 + __complex_asin(__complex__ _Float128 __z) + { return __builtin_casinf128(__z); } - inline _GLIBCXX_CONSTEXPR - complex::complex(const complex& __z) - : _M_value(__z.__rep()) { } -#endif + inline __complex__ _Float128 + __complex_atan(__complex__ _Float128 __z) + { return __builtin_catanf128(__z); } - // Inhibit implicit instantiations for required instantiations, - // which are defined via explicit instantiations elsewhere. - // NB: This syntax is a GNU extension. -#if _GLIBCXX_EXTERN_TEMPLATE - extern template istream& operator>>(istream&, complex&); - extern template ostream& operator<<(ostream&, const complex&); - extern template istream& operator>>(istream&, complex&); - extern template ostream& operator<<(ostream&, const complex&); - extern template istream& operator>>(istream&, complex&); - extern template ostream& operator<<(ostream&, const complex&); + inline __complex__ _Float128 + __complex_acosh(__complex__ _Float128 __z) + { return __builtin_cacoshf128(__z); } -#ifdef _GLIBCXX_USE_WCHAR_T - extern template wistream& operator>>(wistream&, complex&); - extern template wostream& operator<<(wostream&, const complex&); - extern template wistream& operator>>(wistream&, complex&); - extern template wostream& operator<<(wostream&, const complex&); - extern template wistream& operator>>(wistream&, complex&); - extern template wostream& operator<<(wostream&, const complex&); -#endif -#endif + inline __complex__ _Float128 + __complex_asinh(__complex__ _Float128 __z) + { return __builtin_casinhf128(__z); } - /// @} group complex_numbers + inline __complex__ _Float128 + __complex_atanh(__complex__ _Float128 __z) + { return __builtin_catanhf128(__z); } +#endif -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ decltype(0.0bf16) + __complex_acos(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cacosf(__z)); } -#if __cplusplus >= 201103L + inline __complex__ decltype(0.0bf16) + __complex_asin(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_casinf(__z)); } -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION + inline __complex__ decltype(0.0bf16) + __complex_atan(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_catanf(__z)); } - // Forward declarations. - template std::complex<_Tp> acos(const std::complex<_Tp>&); - template std::complex<_Tp> asin(const std::complex<_Tp>&); - template std::complex<_Tp> atan(const std::complex<_Tp>&); + inline __complex__ decltype(0.0bf16) + __complex_acosh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cacoshf(__z)); } - template std::complex<_Tp> acosh(const std::complex<_Tp>&); - template std::complex<_Tp> asinh(const std::complex<_Tp>&); - template std::complex<_Tp> atanh(const std::complex<_Tp>&); - // DR 595. - template _Tp fabs(const std::complex<_Tp>&); + inline __complex__ decltype(0.0bf16) + __complex_asinh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_casinhf(__z)); } - template - inline std::complex<_Tp> - __complex_acos(const std::complex<_Tp>& __z) - { - const std::complex<_Tp> __t = std::asin(__z); - const _Tp __pi_2 = 1.5707963267948966192313216916397514L; - return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag()); - } + inline __complex__ decltype(0.0bf16) + __complex_atanh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_catanhf(__z)); } +#endif +#endif #if _GLIBCXX_USE_C99_COMPLEX_TR1 inline __complex__ float @@ -2247,162 +2403,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __complex_atanh(__z); } #endif -#if _GLIBCXX_USE_C99_COMPLEX_TR1 -#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - inline __complex__ _Float16 - __complex_acos(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_cacosf(__z)); } - - inline __complex__ _Float16 - __complex_asin(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_casinf(__z)); } - - inline __complex__ _Float16 - __complex_atan(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_catanf(__z)); } - - inline __complex__ _Float16 - __complex_acosh(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_cacoshf(__z)); } - - inline __complex__ _Float16 - __complex_asinh(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_casinhf(__z)); } - - inline __complex__ _Float16 - __complex_atanh(__complex__ _Float16 __z) - { return static_cast<__complex__ _Float16>(__builtin_catanhf(__z)); } -#endif - -#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - inline __complex__ _Float32 - __complex_acos(__complex__ _Float32 __z) - { return __builtin_cacosf(__z); } - - inline __complex__ _Float32 - __complex_asin(__complex__ _Float32 __z) - { return __builtin_casinf(__z); } - - inline __complex__ _Float32 - __complex_atan(__complex__ _Float32 __z) - { return __builtin_catanf(__z); } - - inline __complex__ _Float32 - __complex_acosh(__complex__ _Float32 __z) - { return __builtin_cacoshf(__z); } - - inline __complex__ _Float32 - __complex_asinh(__complex__ _Float32 __z) - { return __builtin_casinhf(__z); } - - inline __complex__ _Float32 - __complex_atanh(__complex__ _Float32 __z) - { return __builtin_catanhf(__z); } -#endif - -#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) - inline __complex__ _Float64 - __complex_acos(__complex__ _Float64 __z) - { return __builtin_cacos(__z); } - - inline __complex__ _Float64 - __complex_asin(__complex__ _Float64 __z) - { return __builtin_casin(__z); } - - inline __complex__ _Float64 - __complex_atan(__complex__ _Float64 __z) - { return __builtin_catan(__z); } - - inline __complex__ _Float64 - __complex_acosh(__complex__ _Float64 __z) - { return __builtin_cacosh(__z); } - - inline __complex__ _Float64 - __complex_asinh(__complex__ _Float64 __z) - { return __builtin_casinh(__z); } - - inline __complex__ _Float64 - __complex_atanh(__complex__ _Float64 __z) - { return __builtin_catanh(__z); } -#endif - -#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) - inline __complex__ _Float128 - __complex_acos(__complex__ _Float128 __z) - { return __builtin_cacosl(__z); } - - inline __complex__ _Float128 - __complex_asin(__complex__ _Float128 __z) - { return __builtin_casinl(__z); } - - inline __complex__ _Float128 - __complex_atan(__complex__ _Float128 __z) - { return __builtin_catanl(__z); } - - inline __complex__ _Float128 - __complex_acosh(__complex__ _Float128 __z) - { return __builtin_cacoshl(__z); } - - inline __complex__ _Float128 - __complex_asinh(__complex__ _Float128 __z) - { return __builtin_casinhl(__z); } - - inline __complex__ _Float128 - __complex_atanh(__complex__ _Float128 __z) - { return __builtin_catanhl(__z); } -#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) - inline __complex__ _Float128 - __complex_acos(__complex__ _Float128 __z) - { return __builtin_cacosf128(__z); } - - inline __complex__ _Float128 - __complex_asin(__complex__ _Float128 __z) - { return __builtin_casinf128(__z); } - - inline __complex__ _Float128 - __complex_atan(__complex__ _Float128 __z) - { return __builtin_catanf128(__z); } - - inline __complex__ _Float128 - __complex_acosh(__complex__ _Float128 __z) - { return __builtin_cacoshf128(__z); } - - inline __complex__ _Float128 - __complex_asinh(__complex__ _Float128 __z) - { return __builtin_casinhf128(__z); } - - inline __complex__ _Float128 - __complex_atanh(__complex__ _Float128 __z) - { return __builtin_catanhf128(__z); } -#endif - -#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - inline __complex__ decltype(0.0bf16) - __complex_acos(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cacosf(__z)); } - - inline __complex__ decltype(0.0bf16) - __complex_asin(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_casinf(__z)); } - - inline __complex__ decltype(0.0bf16) - __complex_atan(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_catanf(__z)); } - - inline __complex__ decltype(0.0bf16) - __complex_acosh(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cacoshf(__z)); } - - inline __complex__ decltype(0.0bf16) - __complex_asinh(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_casinhf(__z)); } - - inline __complex__ decltype(0.0bf16) - __complex_atanh(__complex__ decltype(0.0bf16) __z) - { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_catanhf(__z)); } -#endif -#endif - template inline _Tp /// fabs(__z) [8.1.8]. -- 2.7.4