#ifndef SPROUT_COMPLEX_TRANSCENDENTALS_HPP #define SPROUT_COMPLEX_TRANSCENDENTALS_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sprout { // 26.4.8, transcendentals: template SPROUT_CONSTEXPR sprout::complex acos(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex asin(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex atan(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex acosh(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex asinh(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex atanh(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex cos(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex cosh(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex exp(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex log(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex log10(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, T const& y); template SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, sprout::complex const& y); template SPROUT_CONSTEXPR sprout::complex pow(T const& x, sprout::complex const& y); template SPROUT_CONSTEXPR sprout::complex sin(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex sinh(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex sqrt(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex tan(sprout::complex const& x); template SPROUT_CONSTEXPR sprout::complex tanh(sprout::complex const& x); // // acos // asin // atan // namespace detail { template inline SPROUT_CONSTEXPR sprout::complex acos_impl(sprout::complex const& t) { return sprout::complex(sprout::math::half_pi() - t.real(), -t.imag()); } } // namespace detail template inline SPROUT_CONSTEXPR sprout::complex acos(sprout::complex const& x) { return sprout::detail::acos_impl(sprout::asin(x)); } namespace detail { template inline SPROUT_CONSTEXPR sprout::complex asin_impl(sprout::complex const& t) { return sprout::complex(t.imag(), -t.real()); } } // namespace detail template inline SPROUT_CONSTEXPR sprout::complex asin(sprout::complex const& x) { return sprout::detail::asin_impl(sprout::asinh(sprout::complex(-x.imag(), x.real()))); } namespace detail { template inline SPROUT_CONSTEXPR sprout::complex atan_impl_1(sprout::complex const& x, T const& r2, T const& z, T const& num, T const& den) { return sprout::complex( T(0.5) * sprout::atan2(T(2) * x.real(), z), T(0.25) * sprout::log((r2 + num * num) / (r2 + den * den)) ); } template inline SPROUT_CONSTEXPR sprout::complex atan_impl(sprout::complex const& x, T const& r2) { return sprout::detail::atan_impl_1( x, r2, T(1) - r2 - x.imag() * x.imag(), x.imag() + T(1), x.imag() - T(1) ); } } // namespace detail template inline SPROUT_CONSTEXPR sprout::complex atan(sprout::complex const& x) { return sprout::detail::atan_impl(x, x.real() * x.real()); } // // acosh // asinh // atanh // template inline SPROUT_CONSTEXPR sprout::complex acosh(sprout::complex const& x) { return T(2) * sprout::log(sprout::sqrt(T(0.5) * (x + T(1))) + sprout::sqrt(T(0.5) * (x - T(1)))); } template inline SPROUT_CONSTEXPR sprout::complex asinh(sprout::complex const& x) { return sprout::log( sprout::sqrt( sprout::complex( (x.real() - x.imag()) * (x.real() + x.imag()) + T(1), T(2) * x.real() * x.imag() ) ) + x ); } namespace detail { template inline SPROUT_CONSTEXPR sprout::complex atanh_impl_1(sprout::complex const& x, T const& i2, T const& z, T const& num, T const& den) { return sprout::complex( T(0.25) * (sprout::log(i2 + num * num) - sprout::log(i2 + den * den)), T(0.5) * sprout::atan2(T(2) * x.imag(), z) ); } template inline SPROUT_CONSTEXPR sprout::complex atanh_impl(sprout::complex const& x, T const& i2) { return sprout::detail::atanh_impl_1( x, i2, T(1) - i2 - x.real() * x.real(), T(1) + x.imag(), T(1) - x.imag() ); } } // namespace detail template inline SPROUT_CONSTEXPR sprout::complex atanh(sprout::complex const& x) { return sprout::detail::atanh_impl(x, x.imag() * x.imag()); } // // cos // cosh // template inline SPROUT_CONSTEXPR sprout::complex cos(sprout::complex const& x) { return sprout::complex( sprout::cos(x.real()) * sprout::cosh(x.imag()), -(sprout::sin(x.real()) * sprout::sinh(x.imag())) ); } template inline SPROUT_CONSTEXPR sprout::complex cosh(sprout::complex const& x) { return sprout::complex( sprout::cosh(x.real()) * sprout::cos(x.imag()), sprout::sinh(x.real()) * sprout::sin(x.imag()) ); } // // exp // log // log10 // template inline SPROUT_CONSTEXPR sprout::complex exp(sprout::complex const& x) { return sprout::polar(sprout::exp(x.real()), x.imag()); } template inline SPROUT_CONSTEXPR sprout::complex log(sprout::complex const& x) { return sprout::complex(sprout::log(sprout::abs(x)), sprout::arg(x)); } template inline SPROUT_CONSTEXPR sprout::complex log10(sprout::complex const& x) { return sprout::log(x) / sprout::log(T(10)); } namespace detail { template inline SPROUT_CONSTEXPR sprout::complex pow_impl(sprout::complex const& t, T const& y) { return sprout::polar(sprout::exp(y * t.real()), y * t.imag()); } } // namespace detail // // pow // template inline SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, T const& y) { return x == T() ? T() : x.imag() == T() && x.real() > T() ? sprout::pow(x.real(), y) : sprout::detail::pow_impl(sprout::log(x), y) ; } template inline SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, sprout::complex const& y) { return x == T() ? T() : sprout::exp(y * sprout::log(x)) ; } template inline SPROUT_CONSTEXPR sprout::complex pow(T const& x, sprout::complex const& y) { return x > T() ? sprout::polar(sprout::pow(x, y.real()), y.imag() * sprout::log(x)) : sprout::pow(sprout::complex(x), y) ; } // // sin // sinh // template inline SPROUT_CONSTEXPR sprout::complex sin(sprout::complex const& x) { return sprout::complex( sprout::sin(x.real()) * sprout::cosh(x.imag()), sprout::cos(x.real()) * sprout::sinh(x.imag()) ); } template inline SPROUT_CONSTEXPR sprout::complex sinh(sprout::complex const& x) { return sprout::complex( sprout::sinh(x.real()) * sprout::cos(x.imag()), sprout::cosh(x.real()) * sprout::sin(x.imag()) ); } // // sqrt // namespace detail { template inline SPROUT_CONSTEXPR sprout::complex sqrt_impl_1(sprout::complex const& x, T const& t) { return sprout::complex(t, x.imag() < T() ? -t : t); } template inline SPROUT_CONSTEXPR sprout::complex sqrt_impl_2_1(sprout::complex const& x, T const& t, T const& u) { return x.real() > T() ? sprout::complex(u, x.imag() / t) : sprout::complex(sprout::abs(x.imag()) / t, x.imag() < T() ? -u : u) ; } template inline SPROUT_CONSTEXPR sprout::complex sqrt_impl_2(sprout::complex const& x, T const& t) { return sprout::detail::sqrt_impl_2_1(x, t, t / 2); } } // namespace detail // // tan // tanh // template inline SPROUT_CONSTEXPR sprout::complex sqrt(sprout::complex const& x) { return x.real() == T() ? sprout::detail::sqrt_impl_1(x, sprout::sqrt(abs(x.imag()) / 2)) : sprout::detail::sqrt_impl_2(x, sprout::sqrt(2 * (sprout::abs(x) + sprout::abs(x.real())))) ; } template inline SPROUT_CONSTEXPR sprout::complex tan(sprout::complex const& x) { return sprout::sin(x) / sprout::cos(x); } template inline SPROUT_CONSTEXPR sprout::complex tanh(sprout::complex const& x) { return sprout::sinh(x) / sprout::cosh(x); } } // namespace sprout #endif // #ifndef SPROUT_COMPLEX_TRANSCENDENTALS_HPP