#include #include #include #include template struct _complex_t; template<> struct _complex_t { using type = __complex__ float; }; template<> struct _complex_t { using type = __complex__ double; }; template<> struct _complex_t { using type = __complex__ long double; }; template using _complex = _complex_t::type; template static constexpr T _cabs(_complex z) { return BAN::Math::sqrt(creal(z) * creal(z) + cimag(z) * cimag(z)); } template static constexpr T _carg(_complex z) { return BAN::Math::atan2(cimag(z), creal(z)); } template static constexpr _complex _cproj(_complex z) { if (!isfinite(creal(z)) || !isfinite(cimag(z))) return INFINITY + I * copysign(0.0, cimag(z)); return z; } template static constexpr _complex _conj(_complex z) { cimag(z) = -cimag(z); return z; } template static constexpr _complex _cexp(_complex z) { T sin, cos; BAN::Math::sincos(cimag(z), sin, cos); return BAN::Math::exp(creal(z)) * (cos + sin * I); } template static constexpr _complex _clog(_complex z) { return BAN::Math::log(_cabs(z)) + I * _carg(z); } template static constexpr _complex _csqrt(_complex z) { return BAN::Math::sqrt(_cabs(z)) * _cexp(I * _carg(z) / 2); } template static constexpr _complex _csin(_complex z) { return (_cexp(z * I) - _cexp(-z * I)) / 2i; } template static constexpr _complex _ccos(_complex z) { return (_cexp(z * I) + _cexp(-z * I)) / 2i; } template static constexpr _complex _ctan(_complex z) { const _complex exp_pos = _cexp(+I * z); const _complex exp_neg = _cexp(-I * z); return -I * (exp_pos - exp_neg) / (exp_pos + exp_neg); } template static constexpr _complex _cpow(_complex x, _complex y) { const T ln_r = BAN::Math::log(_cabs(x)); const T theta = _carg(x); const T a = creal(y); const T b = cimag(y); return BAN::Math::exp(a * ln_r - b * theta) * _cexp(I * (a * theta + b * ln_r)); } template static constexpr _complex _casin(_complex z) { return -I * _clog(_csqrt(1 - z * z) + I * z); } template static constexpr _complex _cacos(_complex z) { return -I * _clog(I * _csqrt(1 - z * z) + z); } template static constexpr _complex _catan(_complex z) { return -I / 2 * _clog((I - z) / (I + z)); } template static constexpr _complex _csinh(_complex z) { return (_cexp(z) - _cexp(-z)) / 2; } template static constexpr _complex _ccosh(_complex z) { return (_cexp(z) + _cexp(-z)) / 2; } template static constexpr _complex _ctanh(_complex z) { const _complex exp2x = _cexp(2 * z); return (exp2x - 1) / (exp2x + 1); } template static constexpr _complex _casinh(_complex z) { return _clog(z + _csqrt(z * z + 1)); } template static constexpr _complex _cacosh(_complex z) { return _clog(z + _csqrt(z * z - 1)); } template static constexpr _complex _catanh(_complex z) { return _clog((1 + z) / (1 - z)) / 2; } #define COMPLEX_FUNCS(func) \ float func##f(float complex a) { return _##func(a); } \ double func(double complex a) { return _##func(a); } \ long double func##l(long double complex a) { return _##func(a); } COMPLEX_FUNCS(cabs) COMPLEX_FUNCS(carg) #undef COMPLEX_FUNCS #define COMPLEX_FUNCS(func) \ float complex func##f(float complex a) { return _##func(a); } \ double complex func(double complex a) { return _##func(a); } \ long double complex func##l(long double complex a) { return _##func(a); } COMPLEX_FUNCS(cproj) COMPLEX_FUNCS(conj) COMPLEX_FUNCS(cexp) COMPLEX_FUNCS(ctan) COMPLEX_FUNCS(clog) COMPLEX_FUNCS(csin) COMPLEX_FUNCS(ccos) COMPLEX_FUNCS(csqrt) COMPLEX_FUNCS(csinh) COMPLEX_FUNCS(ccosh) COMPLEX_FUNCS(ctanh) COMPLEX_FUNCS(cacos) COMPLEX_FUNCS(casin) COMPLEX_FUNCS(catan) COMPLEX_FUNCS(cacosh) COMPLEX_FUNCS(casinh) COMPLEX_FUNCS(catanh) #undef COMPLEX_FUNCS #define COMPLEX_FUNCS(func) \ float complex func##f(float complex a, float complex b) { return _##func(a, b); } \ double complex func(double complex a, double complex b) { return _##func(a, b); } \ long double complex func##l(long double complex a, long double complex b) { return _##func(a, b); } COMPLEX_FUNCS(cpow) #undef COMPLEX_FUNCS