inline SPROUT_CONSTEXPR sprout::math::quaternion<T> operator*(sprout::math::quaternion<T> const& lhs, sprout::complex<T> const& rhs) { return sprout::math::detail::mul_qc_impl( rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4(), lhs.real(), lhs.imag() ); }
inline SPROUT_CONSTEXPR sprout::math::quaternion<T> operator/(sprout::math::quaternion<T> const& lhs, sprout::complex<T> const& rhs) { return sprout::math::detail::div_qq_impl( lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), sprout::array<T, 4>{{rhs.real(), rhs.imag(), static_cast<T>(0), static_cast<T>(0)}} ); }
inline SPROUT_CONSTEXPR sprout::complex<T> proj_impl(sprout::complex<T> const& x, T const& den) { return sprout::complex<T>( T(2) * x.real() / den, T(2) * x.imag() / den ); }
inline SPROUT_CONSTEXPR sprout::complex<T> copysign_mul(T const& t, sprout::complex<T> const& z) { return sprout::complex<T>( sprout::math::copysign(t, z.real()), sprout::math::copysign(t, z.imag()) ); }
inline SPROUT_CONSTEXPR bool operator==(sprout::math::quaternion<T> const& lhs, sprout::complex<T> const& rhs) { return lhs.R_component_1() == rhs.real() && lhs.R_component_2() == rhs.imag() && lhs.R_component_3() == static_cast<T>(0) && lhs.R_component_4() == static_cast<T>(0) ; }
inline SPROUT_CONSTEXPR sprout::math::quaternion<T> operator+(sprout::math::quaternion<T> const& lhs, sprout::complex<T> const& rhs) { return sprout::math::quaternion<T>( lhs.R_component_1() + rhs.real(), lhs.R_component_2() + rhs.imag(), lhs.R_component_3(), lhs.R_component_4() ); }
inline SPROUT_CONSTEXPR sprout::complex<T> operator*(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) { return sprout::complex<T>( lhs.real() * rhs.real() - lhs.imag() * rhs.imag(), lhs.real() * rhs.imag() + lhs.imag() * rhs.real() ); }
inline SPROUT_CONSTEXPR sprout::complex<T> divides_impl(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs, T const& n) { return sprout::complex<T>( (lhs.real() * rhs.real() + lhs.imag() * rhs.imag()) / n, (lhs.imag() * rhs.real() - lhs.real() * rhs.imag()) / n ); }
inline SPROUT_CONSTEXPR T arg(sprout::complex<T> const& x) { return sprout::math::atan2(x.imag(), x.real()); }
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(T const& lhs, sprout::complex<T> const& rhs) { return sprout::complex<T>(lhs - rhs.real(), -rhs.imag()); }
inline SPROUT_CONSTEXPR bool operator==(T const& lhs, sprout::complex<T> const& rhs) { return lhs == rhs.real() && T() == rhs.imag(); }
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(sprout::complex<T> const& x) { return sprout::complex<T>(-x.real(), -x.imag()); }
inline SPROUT_CONSTEXPR T norm(sprout::complex<T> const& x) { return x.real() * x.real() + x.imag() * x.imag(); }
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt(sprout::complex<T> const& x) { typedef sprout::complex<T> type; return sprout::math::isinf(x.imag()) ? type(sprout::numeric_limits<T>::infinity(), x.imag()) : sprout::math::isnan(x.real()) ? sprout::math::isnan(x.imag()) ? type(sprout::numeric_limits<T>::quiet_NaN(), sprout::numeric_limits<T>::quiet_NaN()) : type(sprout::numeric_limits<T>::quiet_NaN(), sprout::numeric_limits<T>::quiet_NaN()) : sprout::math::isnan(x.imag()) ? x.real() == sprout::numeric_limits<T>::infinity() ? type(sprout::numeric_limits<T>::infinity(), sprout::math::copysign(sprout::numeric_limits<T>::quiet_NaN(), x.imag())) : x.real() == -sprout::numeric_limits<T>::infinity() ? type( sprout::math::copysign(sprout::numeric_limits<T>::quiet_NaN(), x.imag()), sprout::math::copysign(sprout::numeric_limits<T>::infinity(), x.imag()) ) : type(sprout::numeric_limits<T>::quiet_NaN(), sprout::numeric_limits<T>::quiet_NaN()) : x.real() == sprout::numeric_limits<T>::infinity() ? type(sprout::numeric_limits<T>::infinity(), (x.imag() == 0 ? x.imag() : sprout::math::copysign(T(0), x.imag()))) : x.real() == -sprout::numeric_limits<T>::infinity() ? type(T(0), sprout::math::copysign(T(0), x.imag())) : x.real() == 0 && x.imag() == 0 ? type(T(0), x.imag()) : x.real() == 0 ? sprout::detail::sqrt_impl_1(x, sprout::math::sqrt(sprout::math::abs(x.imag()) / T(2))) : sprout::detail::sqrt_impl_2(x, sprout::math::sqrt(T(2) * (sprout::abs(x) + sprout::math::abs(x.real())))) ; }
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_1(sprout::complex<T> const& x, T const& t) { return sprout::complex<T>(t, sprout::math::signbit(x.imag()) ? -t : t); }
inline SPROUT_CONSTEXPR std::size_t hash_value(sprout::complex<T> const& v) { return sprout::hash_values(v.real(), v.imag()); }
inline SPROUT_CONSTEXPR sprout::complex<T> atanh(sprout::complex<T> const& x) { typedef sprout::complex<T> type; return sprout::math::isnan(x.real()) ? sprout::math::isnan(x.imag()) ? type(x.imag(), x.imag()) : sprout::math::isinf(x.imag()) ? type(sprout::math::copysign(T(0), x.real()), sprout::math::copysign(sprout::math::half_pi<T>(), x.imag())) : type(x.real(), x.real()) : sprout::math::isnan(x.imag()) ? sprout::math::isinf(x.real()) ? type(sprout::math::copysign(T(0), x.real()), x.imag()) : x.real() == 0 ? x : type(x.imag(), x.imag()) : sprout::math::isinf(x.real()) || sprout::math::isinf(x.imag()) ? type(sprout::math::copysign(T(0), x.real()), sprout::math::copysign(sprout::math::half_pi<T>(), x.imag())) : x.real() == 0 && x.imag() == 0 ? x : (x.real() == 1 || x.real() == -1) && x.imag() == 0 ? type(sprout::math::copysign(sprout::numeric_limits<T>::infinity(), x.real()), x.imag()) : (sprout::log(T(1) + x) - sprout::log(T(1) - x)) / T(2) ; }
inline SPROUT_CONSTEXPR sprout::complex<T> acosh(sprout::complex<T> const& x) { typedef sprout::complex<T> type; return sprout::math::isnan(x.real()) ? sprout::math::isnan(x.imag()) ? x : sprout::math::isinf(x.imag()) ? type(sprout::numeric_limits<T>::infinity(), x.real()) : type(x.real(), x.real()) : sprout::math::isnan(x.imag()) ? sprout::math::isinf(x.real()) ? type(sprout::numeric_limits<T>::infinity(), x.imag()) : type(sprout::numeric_limits<T>::quiet_NaN(), x.imag()) : x.real() == sprout::numeric_limits<T>::infinity() ? sprout::math::isinf(x.imag()) ? type(sprout::numeric_limits<T>::infinity(), sprout::math::copysign(sprout::math::quarter_pi<T>(), x.imag())) : type(sprout::numeric_limits<T>::infinity(), (x.imag() == 0 ? x.imag() : sprout::math::copysign(T(0), x.imag()))) : x.real() == -sprout::numeric_limits<T>::infinity() ? sprout::math::isinf(x.imag()) ? type(sprout::numeric_limits<T>::infinity(), sprout::math::copysign(sprout::math::three_quarters_pi<T>(), x.imag())) : type(sprout::numeric_limits<T>::infinity(), sprout::math::copysign(sprout::math::pi<T>(), x.imag())) : sprout::math::isinf(x.imag()) ? type(sprout::numeric_limits<T>::infinity(), sprout::math::copysign(sprout::math::half_pi<T>(), x.imag())) : x.real() == 0 && x.imag() == 0 ? type(T(0), sprout::math::copysign(sprout::math::half_pi<T>(), x.imag())) : T(2) * sprout::log(sprout::sqrt(sprout::math::half<T>() * (x + T(1))) + sprout::sqrt(sprout::math::half<T>() * (x - T(1)))) ; }
inline SPROUT_CONSTEXPR sprout::complex<T> operator/(sprout::complex<T> const& lhs, T const& rhs) { return sprout::complex<T>(lhs.real() / rhs, lhs.imag() / rhs); }
inline SPROUT_CONSTEXPR sprout::complex<T> acos_impl(sprout::complex<T> const& t) { return sprout::complex<T>(sprout::math::half_pi<T>() - t.real(), -t.imag()); }
inline SPROUT_CONSTEXPR sprout::complex<T> log2_impl(sprout::complex<T> const& z) { return sprout::math::isnan(z.real()) || sprout::math::isnan(z.imag()) ? z : z / sprout::math::ln_two<T>() ; }
inline SPROUT_CONSTEXPR sprout::complex<T> acos(sprout::complex<T> const& x) { typedef sprout::complex<T> type; return sprout::math::isnan(x.real()) ? sprout::math::isnan(x.imag()) ? x : sprout::math::isinf(x.imag()) ? type(x.real(), -x.imag()) : type(x.real(), sprout::numeric_limits<T>::quiet_NaN()) : sprout::math::isnan(x.imag()) ? sprout::math::isinf(x.real()) ? type(sprout::numeric_limits<T>::quiet_NaN(), x.real()) : x.real() == 0 ? type(sprout::math::half_pi<T>(), x.imag()) : type(sprout::numeric_limits<T>::quiet_NaN(), sprout::numeric_limits<T>::quiet_NaN()) : x.real() == sprout::numeric_limits<T>::infinity() ? sprout::math::isinf(x.imag()) ? type(sprout::math::quarter_pi<T>(), -x.imag()) : type(T(0), sprout::math::copysign(sprout::numeric_limits<T>::infinity(), -x.imag())) : x.real() == -sprout::numeric_limits<T>::infinity() ? sprout::math::isinf(x.imag()) ? type(sprout::math::three_quarters_pi<T>(), -x.imag()) : type(sprout::math::pi<T>(), sprout::math::copysign(sprout::numeric_limits<T>::infinity(), -x.imag())) : sprout::math::isinf(x.imag()) ? type(sprout::math::half_pi<T>(), sprout::math::copysign(sprout::numeric_limits<T>::infinity(), -x.imag())) : x.real() == 0 && x.imag() == 0 ? type(sprout::math::half_pi<T>(), -x.imag()) : sprout::detail::acos_impl(sprout::asin(x)) ; }
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_2_1(sprout::complex<T> const& x, T const& t, T const& u) { return x.real() > T(0) ? sprout::complex<T>(u, x.imag() / t) : sprout::complex<T>(sprout::math::abs(x.imag()) / t, sprout::math::signbit(x.imag()) ? -u : u) ; }
inline SPROUT_CONSTEXPR sprout::complex<T> round(sprout::complex<T> const& x) { return sprout::complex<T>(sprout::round(x.real()), sprout::round(x.imag())); }
inline SPROUT_CONSTEXPR sprout::complex<T> exp(sprout::complex<T> const& x) { typedef sprout::complex<T> type; return sprout::math::isnan(x.real()) ? sprout::math::isnan(x.imag()) ? type(x.real(), x.real()) : x.imag() == 0 ? type(x.real(), x.imag()) : type(x.real(), x.real()) : sprout::math::isnan(x.imag()) ? x.real() == sprout::numeric_limits<T>::infinity() ? type(x.real(), x.imag()) : x.real() == -sprout::numeric_limits<T>::infinity() ? type(T(0), T(0)) : sprout::math::isinf(x.real()) ? type(sprout::numeric_limits<T>::infinity(), sprout::numeric_limits<T>::quiet_NaN()) : type(x.imag(), x.imag()) : x.real() == sprout::numeric_limits<T>::infinity() ? sprout::math::isinf(x.imag()) ? type(sprout::numeric_limits<T>::infinity(), sprout::numeric_limits<T>::quiet_NaN()) : x.imag() == 0 ? type(sprout::numeric_limits<T>::infinity(), x.imag()) : sprout::detail::copysign_mul(sprout::numeric_limits<T>::infinity(), sprout::euler(x.imag())) : x.real() == -sprout::numeric_limits<T>::infinity() ? sprout::math::isinf(x.imag()) ? type(T(0), T(0)) : T(0) * sprout::euler(x.imag()) : sprout::math::isinf(x.imag()) ? type(-sprout::numeric_limits<T>::quiet_NaN(), -sprout::numeric_limits<T>::quiet_NaN()) : x.real() == 0 && x.imag() == 0 ? type(T(1), x.imag()) : sprout::polar(sprout::math::exp(x.real()), x.imag()) ; }
inline SPROUT_CONSTEXPR sprout::complex<T> tanh(sprout::complex<T> const& x) { typedef sprout::complex<T> type; return sprout::math::isnan(x.real()) ? sprout::math::isnan(x.imag()) ? x : x.imag() == 0 ? x : type(x.real(), x.real()) : sprout::math::isnan(x.imag()) ? sprout::math::isinf(x.real()) ? type(T(1), T(0)) : type(x.imag(), x.imag()) : sprout::math::isinf(x.real()) ? sprout::math::isinf(x.imag()) ? type(T(1), T(0)) : type(T(1), T(0) * sprout::math::sin(T(2) * x.imag())) : sprout::math::isinf(x.imag()) ? type(-sprout::numeric_limits<T>::quiet_NaN(), -sprout::numeric_limits<T>::quiet_NaN()) : x.real() == 0 && x.imag() == 0 ? x : sprout::sinh(x) / sprout::cosh(x) ; }