diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating12.C b/gcc/testsuite/g++.dg/cpp23/ext-floating12.C new file mode 100644 index 00000000000..77ee4c70a93 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/ext-floating12.C @@ -0,0 +1,182 @@ +// P1467R9 - Extended floating-point types and standard names. +// { dg-do compile { target { c++23 && { i?86-*-linux* x86_64-*-linux* } } } } +// { dg-options "" } + +#include +#include + +#if !defined(__STDCPP_FLOAT32_T__) \ + || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \ + || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \ + || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \ + || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ >= __FLT128_MANT_DIG__ \ + || !defined(__SIZEOF_FLOAT128__) +#error Unexpected set of floating point types +#endif + +using namespace std; + +int +main() +{ + complex a01(complex(1.0f, 2.0f)); + complex a02 = complex(1.0f, 2.0f); + complex a03(complex(1.0, 2.0)); + complex a04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex' requested" } + complex a05(complex(1.0L, 2.0L)); + complex a06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex' requested" } + complex a07(complex(1.0f32, 2.0f32)); + complex a08 = complex(1.0f32, 2.0f32); + complex a09(complex(1.0f64, 2.0f64)); + complex a10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex' requested" } + complex a11(complex(1.0f128, 2.0f128)); + complex a12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex a13(complex(1.0f16, 2.0f16)); + complex a14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex a15(complex(1.0bf16, 2.0bf16)); + complex a16 = complex(1.0bf16, 2.0bf16); +#endif + complex b01(complex(1.0f, 2.0f)); + complex b02 = complex(1.0f, 2.0f); + complex b03(complex(1.0, 2.0)); + complex b04 = complex(1.0, 2.0); + complex b05(complex(1.0L, 2.0L)); + complex b06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex' requested" } + complex b07(complex(1.0f32, 2.0f32)); + complex b08 = complex(1.0f32, 2.0f32); + complex b09(complex(1.0f64, 2.0f64)); + complex b10 = complex(1.0f64, 2.0f64); + complex b11(complex(1.0f128, 2.0f128)); + complex b12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex b13(complex(1.0f16, 2.0f16)); + complex b14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex b15(complex(1.0bf16, 2.0bf16)); + complex b16 = complex(1.0bf16, 2.0bf16); +#endif + complex c01(complex(1.0f, 2.0f)); + complex c02 = complex(1.0f, 2.0f); + complex c03(complex(1.0, 2.0)); + complex c04 = complex(1.0, 2.0); + complex c05(complex(1.0L, 2.0L)); + complex c06 = complex(1.0L, 2.0L); + complex c07(complex(1.0f32, 2.0f32)); + complex c08 = complex(1.0f32, 2.0f32); + complex c09(complex(1.0f64, 2.0f64)); + complex c10 = complex(1.0f64, 2.0f64); + complex c11(complex(1.0f128, 2.0f128)); + complex c12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex c13(complex(1.0f16, 2.0f16)); + complex c14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex c15(complex(1.0bf16, 2.0bf16)); + complex c16 = complex(1.0bf16, 2.0bf16); +#endif + complex d01(complex(1.0f, 2.0f)); + complex d02 = complex(1.0f, 2.0f); + complex d03(complex(1.0, 2.0)); + complex d04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float32>' requested" } + complex d05(complex(1.0L, 2.0L)); + complex d06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float32>' requested" } + complex d07(complex(1.0f32, 2.0f32)); + complex d08 = complex(1.0f32, 2.0f32); + complex d09(complex(1.0f64, 2.0f64)); + complex d10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex<_Float32>' requested" } + complex d11(complex(1.0f128, 2.0f128)); + complex d12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<_Float32>' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex d13(complex(1.0f16, 2.0f16)); + complex d14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex d15(complex(1.0bf16, 2.0bf16)); + complex d16 = complex(1.0bf16, 2.0bf16); +#endif + complex e01(complex(1.0f, 2.0f)); + complex e02 = complex(1.0f, 2.0f); + complex e03(complex(1.0, 2.0)); + complex e04 = complex(1.0, 2.0); + complex e05(complex(1.0L, 2.0L)); + complex e06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float64>' requested" } + complex e07(complex(1.0f32, 2.0f32)); + complex e08 = complex(1.0f32, 2.0f32); + complex e09(complex(1.0f64, 2.0f64)); + complex e10 = complex(1.0f64, 2.0f64); + complex e11(complex(1.0f128, 2.0f128)); + complex e12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<_Float64>' requested" } +#ifdef __STDCPP_FLOAT16_T__ + complex e13(complex(1.0f16, 2.0f16)); + complex e14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex e15(complex(1.0bf16, 2.0bf16)); + complex e16 = complex(1.0bf16, 2.0bf16); +#endif + complex f01(complex(1.0f, 2.0f)); + complex f02 = complex(1.0f, 2.0f); + complex f03(complex(1.0, 2.0)); + complex f04 = complex(1.0, 2.0); + complex f05(complex(1.0L, 2.0L)); + complex f06 = complex(1.0L, 2.0L); + complex f07(complex(1.0f32, 2.0f32)); + complex f08 = complex(1.0f32, 2.0f32); + complex f09(complex(1.0f64, 2.0f64)); + complex f10 = complex(1.0f64, 2.0f64); + complex f11(complex(1.0f128, 2.0f128)); + complex f12 = complex(1.0f128, 2.0f128); +#ifdef __STDCPP_FLOAT16_T__ + complex f13(complex(1.0f16, 2.0f16)); + complex f14 = complex(1.0f16, 2.0f16); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex f15(complex(1.0bf16, 2.0bf16)); + complex f16 = complex(1.0bf16, 2.0bf16); +#endif +#ifdef __STDCPP_FLOAT16_T__ + complex g01(complex(1.0f, 2.0f)); + complex g02 = complex(1.0f, 2.0f); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g03(complex(1.0, 2.0)); + complex g04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g05(complex(1.0L, 2.0L)); + complex g06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g07(complex(1.0f32, 2.0f32)); + complex g08 = complex(1.0f32, 2.0f32); // { dg-error "conversion from 'complex<_Float32>' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g09(complex(1.0f64, 2.0f64)); + complex g10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g11(complex(1.0f128, 2.0f128)); + complex g12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<_Float16>' requested" "" { target float16 } } + complex g13(complex(1.0f16, 2.0f16)); + complex g14 = complex(1.0f16, 2.0f16); +#ifdef __STDCPP_BFLOAT16_T__ + complex g15(complex(1.0bf16, 2.0bf16)); + complex g16 = complex(1.0bf16, 2.0bf16); // { dg-error "conversion from 'complex<\[^\n\r]*>' to non-scalar type 'complex<_Float16>' requested" "" { target { float16 && bfloat16 } } } +#endif +#endif +#ifdef __STDCPP_BFLOAT16_T__ + complex h01(complex(1.0f, 2.0f)); + complex h02 = complex(1.0f, 2.0f); // { dg-error "conversion from 'complex' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h03(complex(1.0, 2.0)); + complex h04 = complex(1.0, 2.0); // { dg-error "conversion from 'complex' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h05(complex(1.0L, 2.0L)); + complex h06 = complex(1.0L, 2.0L); // { dg-error "conversion from 'complex' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h07(complex(1.0f32, 2.0f32)); + complex h08 = complex(1.0f32, 2.0f32); // { dg-error "conversion from 'complex<_Float32>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h09(complex(1.0f64, 2.0f64)); + complex h10 = complex(1.0f64, 2.0f64); // { dg-error "conversion from 'complex<_Float64>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } + complex h11(complex(1.0f128, 2.0f128)); + complex h12 = complex(1.0f128, 2.0f128); // { dg-error "conversion from 'complex<_Float128>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target bfloat16 } } +#ifdef __STDCPP_FLOAT16_T__ + complex h13(complex(1.0f16, 2.0f16)); + complex h14 = complex(1.0f16, 2.0f16); // { dg-error "conversion from 'complex<_Float16>' to non-scalar type 'complex<\[^\n\r]*>' requested" "" { target { float16 && bfloat16 } } } +#endif + complex h15(complex(1.0bf16, 2.0bf16)); + complex h16 = complex(1.0bf16, 2.0bf16); +#endif +} diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index 8f91bbedbed..592673a1d11 100644 --- a/libstdc++-v3/include/bits/cpp_type_traits.h +++ b/libstdc++-v3/include/bits/cpp_type_traits.h @@ -315,6 +315,51 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) typedef __true_type __type; }; +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct __is_floating<_Float16> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct __is_floating<_Float32> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct __is_floating<_Float64> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct __is_floating<_Float128> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct __is_floating<__gnu_cxx::__bfloat16_t> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + // // Pointer types // diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 8f9368fd7d0..da2df912ecc 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -142,8 +142,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Converting constructor. template - _GLIBCXX_CONSTEXPR complex(const complex<_Up>& __z) - : _M_real(__z.real()), _M_imag(__z.imag()) { } +#if __cplusplus > 202002L + explicit(!requires(_Up __u) { _Tp{__u}; }) +#endif + _GLIBCXX_CONSTEXPR complex(const complex<_Up>& __z) + : _M_real(_Tp(__z.real())), _M_imag(_Tp(__z.imag())) { } #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1077,6 +1080,264 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : std::pow(complex<_Tp>(__x), __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__ _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 + +#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); } + + inline __complex__ _Float32 + __complex_sqrt(__complex__ _Float32 __z) { return __builtin_csqrtf(__z); } + + inline __complex__ _Float32 + __complex_tan(__complex__ _Float32 __z) { return __builtin_ctanf(__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 + +#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); } + + inline __complex__ _Float64 + __complex_cos(__complex__ _Float64 __z) { return __builtin_ccos(__z); } + + inline __complex__ _Float64 + __complex_cosh(__complex__ _Float64 __z) { return __builtin_ccosh(__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 + +#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); } + + inline __complex__ _Float128 + __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtl(__z); } + + inline __complex__ _Float128 + __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanl(__z); } + + inline __complex__ _Float128 + __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhl(__z); } + + 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); } + + inline _Float128 + __complex_arg(__complex__ _Float128 __z) { return __builtin_cargf128(__z); } + + inline __complex__ _Float128 + __complex_cos(__complex__ _Float128 __z) { return __builtin_ccosf128(__z); } + + inline __complex__ _Float128 + __complex_cosh(__complex__ _Float128 __z) { return __builtin_ccoshf128(__z); } + + inline __complex__ _Float128 + __complex_exp(__complex__ _Float128 __z) { return __builtin_cexpf128(__z); } + + inline __complex__ _Float128 + __complex_log(__complex__ _Float128 __z) { return __builtin_clogf128(__z); } + + inline __complex__ _Float128 + __complex_sin(__complex__ _Float128 __z) { return __builtin_csinf128(__z); } + + inline __complex__ _Float128 + __complex_sinh(__complex__ _Float128 __z) { return __builtin_csinhf128(__z); } + + inline __complex__ _Float128 + __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtf128(__z); } + + inline __complex__ _Float128 + __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanf128(__z); } + + inline __complex__ _Float128 + __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhf128(__z); } + + inline __complex__ _Float128 + __complex_pow(__complex__ _Float128 __x, __complex__ _Float128 __y) + { return __builtin_cpowf128(__x, __y); } +#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)); } + + inline __complex__ decltype(0.0bf16) + __complex_cos(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccosf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_cosh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccoshf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_exp(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cexpf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_log(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_clogf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_sin(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csinf(__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__ decltype(0.0bf16) + __complex_sqrt(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csqrtf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_tan(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_tanh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanhf(__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.3 complex specializations /// complex specialization template<> @@ -1098,8 +1359,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif +#if __cplusplus > 202002L + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } +#else explicit _GLIBCXX_CONSTEXPR complex(const complex&); explicit _GLIBCXX_CONSTEXPR complex(const complex&); +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1244,10 +1512,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif +#if __cplusplus > 202002L + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } +#else _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } explicit _GLIBCXX_CONSTEXPR complex(const complex&); +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1391,11 +1666,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif +#if __cplusplus > 202002L + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } +#else _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1517,6 +1799,161 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ComplexT _M_value; }; +#if __cplusplus > 202002L + template + struct __complex_type + { }; + +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct __complex_type<_Float16> + { typedef __complex__ _Float16 type; }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct __complex_type<_Float32> + { typedef __complex__ _Float32 type; }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct __complex_type<_Float64> + { typedef __complex__ _Float64 type; }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct __complex_type<_Float128> + { typedef __complex__ _Float128 type; }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct __complex_type<__gnu_cxx::__bfloat16_t> + { typedef __complex__ decltype(0.0bf16) type; }; +#endif + + template + requires(__complex_type<_Tp>::type) + class complex<_Tp> + { + public: + typedef _Tp value_type; + typedef std::__complex_type<_Tp>::type _ComplexT; + + constexpr complex(_ComplexT __z) : _M_value(__z) { } + + constexpr complex(_Tp __r = _Tp(), _Tp __i = _Tp()) + : _M_value{ __r, __i } { } + + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } + + constexpr _Tp + real() const { return __real__ _M_value; } + + constexpr _Tp + imag() const { return __imag__ _M_value; } + + constexpr void + real(_Tp __val) { __real__ _M_value = __val; } + + constexpr void + imag(_Tp __val) { __imag__ _M_value = __val; } + + constexpr complex& + operator=(_Tp __f) + { + _M_value = __f; + return *this; + } + + constexpr complex& + operator+=(_Tp __f) + { + _M_value += __f; + return *this; + } + + constexpr complex& + operator-=(_Tp __f) + { + _M_value -= __f; + return *this; + } + + constexpr complex& + operator*=(_Tp __f) + { + _M_value *= __f; + return *this; + } + + constexpr complex& + operator/=(_Tp __f) + { + _M_value /= __f; + return *this; + } + + // Let the compiler synthesize the copy and assignment + // operator. It always does a pretty good job. + constexpr complex& operator=(const complex&) = default; + + template + constexpr complex& + operator=(const complex<_Up>& __z) + { + __real__ _M_value = __z.real(); + __imag__ _M_value = __z.imag(); + return *this; + } + + template + constexpr complex& + operator+=(const complex<_Up>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + constexpr complex& + operator-=(const complex<_Up>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + constexpr complex& + operator*=(const complex<_Up>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + constexpr complex& + operator/=(const complex<_Up>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + constexpr _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; +#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 @@ -1530,6 +1967,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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. @@ -1809,6 +2247,162 @@ _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]. @@ -1897,6 +2491,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline complex __complex_proj(const complex& __z) { return __builtin_cprojl(__z.__rep()); } + +#if __cplusplus > 202002L +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float16 + __complex_proj(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cprojf(__z)); } +#endif + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float32 + __complex_proj(__complex__ _Float32 __z) + { return __builtin_cprojf(__z); } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline __complex__ _Float64 + __complex_proj(__complex__ _Float64 __z) + { return __builtin_cproj(__z); } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline __complex__ _Float128 + __complex_proj(__complex__ _Float128 __z) + { return __builtin_cprojl(__z); } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) + inline __complex__ _Float128 + __complex_proj(__complex__ _Float128 __z) + { return __builtin_cprojf128(__z); } +#endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ decltype(0.0bf16) + __complex_proj(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cprojf(__z)); } +#endif + + template + requires(__complex_type<_Tp>::type) + inline complex<_Tp> + __complex_proj(const complex<_Tp>& __z) + { return __complex_proj(__z.__rep()); } +#endif + #elif defined _GLIBCXX_USE_C99_MATH_TR1 inline complex __complex_proj(const complex& __z) diff --git a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc new file mode 100644 index 00000000000..bdc9af016c7 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc @@ -0,0 +1,89 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2b" } +// { dg-do link { target c++23 } } + +#include +#include + +template +__attribute__((__noipa__)) void +test_functions(T *p, std::complex *q) +{ + p[0] = std::abs(q[0]); + p[1] = std::arg(q[1]); + q[2] = std::cos(q[2]); + q[3] = std::cosh(q[3]); + q[4] = std::exp(q[4]); + q[5] = std::log(q[5]); + q[6] = std::sin(q[6]); + q[7] = std::sinh(q[7]); + q[8] = std::sqrt(q[8]); + q[9] = std::tan(q[9]); + q[10] = std::tanh(q[10]); + q[11] = std::pow(q[11], q[19]); + q[12] = std::acos(q[12]); + q[13] = std::asin(q[13]); + q[14] = std::atan(q[14]); + q[15] = std::acosh(q[15]); + q[16] = std::asinh(q[16]); + q[17] = std::atanh(q[17]); + q[18] = std::proj(q[18]); +} + +int +main() +{ +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::float16_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::float32_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + { + std::float64_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT128_T__) \ + && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ + || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) + { + std::float128_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::bfloat16_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +}