/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_COMPLEX_SQRT_HPP #define SPROUT_COMPLEX_SQRT_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { // // sqrt // // G.6.4.2 The csqrt functions // csqrt(conj(z)) = conj(csqrt(z)). // csqrt(}0 + i0) returns +0 + i0. // csqrt(x + i‡) returns +‡+ i‡, for all x (including NaN). // csqrt(x + iNaN) returns NaN + iNaN and optionally raises the eeinvalidff floating-point exception, for finite x. // csqrt(-‡+ iy) returns +0 + i‡, for finite positive-signed y. // csqrt(+‡+ iy) returns +‡+ i0, for finite positive-signed y. // csqrt(-‡+ iNaN) returns NaN } i‡ (where the sign of the imaginary part of the result is unspecified). // csqrt(+‡+ iNaN) returns +‡+ iNaN. // csqrt(NaN + iy) returns NaN + iNaN and optionally raises the eeinvalidff floating-point exception, for finite y. // csqrt(NaN + iNaN) returns NaN + iNaN. // namespace detail { template inline SPROUT_CONSTEXPR sprout::complex sqrt_impl_1(sprout::complex const& x, T const& t) { return sprout::complex(t, sprout::math::signbit(x.imag()) ? -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(0) ? sprout::complex(u, x.imag() / t) : sprout::complex(sprout::math::abs(x.imag()) / t, sprout::math::signbit(x.imag()) ? -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 / T(2)); } } // namespace detail template inline SPROUT_CONSTEXPR sprout::complex sqrt(sprout::complex const& x) { typedef sprout::complex type; return sprout::math::isinf(x.imag()) ? type(sprout::numeric_limits::infinity(), x.imag()) : sprout::math::isnan(x.real()) ? sprout::math::isnan(x.imag()) ? type(sprout::numeric_limits::quiet_NaN(), sprout::numeric_limits::quiet_NaN()) : type(sprout::numeric_limits::quiet_NaN(), sprout::numeric_limits::quiet_NaN()) : sprout::math::isnan(x.imag()) ? x.real() == sprout::numeric_limits::infinity() ? type(sprout::numeric_limits::infinity(), sprout::math::copysign(sprout::numeric_limits::quiet_NaN(), x.imag())) : x.real() == -sprout::numeric_limits::infinity() ? type( sprout::math::copysign(sprout::numeric_limits::quiet_NaN(), x.imag()), sprout::math::copysign(sprout::numeric_limits::infinity(), x.imag()) ) : type(sprout::numeric_limits::quiet_NaN(), sprout::numeric_limits::quiet_NaN()) : x.real() == sprout::numeric_limits::infinity() ? type(sprout::numeric_limits::infinity(), (x.imag() == 0 ? x.imag() : sprout::math::copysign(T(0), x.imag()))) : x.real() == -sprout::numeric_limits::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())))) ; } } // namespace sprout #endif // #ifndef SPROUT_COMPLEX_SQRT_HPP