Chris@102: /////////////////////////////////////////////////////////////////////////////// Chris@102: // Copyright Christopher Kormanyos 2014. Chris@102: // Copyright John Maddock 2014. Chris@102: // Copyright Paul Bristow 2014. Chris@102: // Distributed under the Boost Software License, Chris@102: // Version 1.0. (See accompanying file LICENSE_1_0.txt Chris@102: // or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: Chris@102: // Implement a specialization of std::complex<> for *anything* that Chris@102: // is defined as BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE. Chris@102: Chris@102: #ifndef _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ Chris@102: #define _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ Chris@102: Chris@102: #if defined(__GNUC__) Chris@102: #pragma GCC system_header Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: Chris@102: namespace std Chris@102: { Chris@102: // Forward declarations. Chris@102: template Chris@102: class complex; Chris@102: Chris@102: template<> Chris@102: class complex; Chris@102: Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex&); Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex&); Chris@102: Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex&); Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex&); Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex&); Chris@102: Chris@102: inline complex conj (const complex&); Chris@102: inline complex proj (const complex&); Chris@102: Chris@102: inline complex polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&, Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& = 0); Chris@102: Chris@102: inline complex sqrt (const complex&); Chris@102: Chris@102: inline complex sin (const complex&); Chris@102: inline complex cos (const complex&); Chris@102: inline complex tan (const complex&); Chris@102: inline complex asin (const complex&); Chris@102: inline complex acos (const complex&); Chris@102: inline complex atan (const complex&); Chris@102: Chris@102: inline complex exp (const complex&); Chris@102: inline complex log (const complex&); Chris@102: inline complex log10(const complex&); Chris@102: Chris@102: inline complex pow (const complex&, Chris@102: int); Chris@102: inline complex pow (const complex&, Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&); Chris@102: inline complex pow (const complex&, Chris@102: const complex&); Chris@102: inline complex pow (const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&, Chris@102: const complex&); Chris@102: Chris@102: inline complex sinh (const complex&); Chris@102: inline complex cosh (const complex&); Chris@102: inline complex tanh (const complex&); Chris@102: Chris@102: inline complex asinh(const complex&); Chris@102: inline complex acosh(const complex&); Chris@102: inline complex atanh(const complex&); Chris@102: Chris@102: template Chris@102: inline std::basic_ostream& operator<<(std::basic_ostream&, const std::complex&); Chris@102: Chris@102: template Chris@102: inline std::basic_istream& operator>>(std::basic_istream&, std::complex&); Chris@102: Chris@102: // Template specialization of the complex class. Chris@102: template<> Chris@102: class complex Chris@102: { Chris@102: public: Chris@102: typedef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE value_type; Chris@102: Chris@102: explicit complex(const complex&); Chris@102: explicit complex(const complex&); Chris@102: explicit complex(const complex&); Chris@102: Chris@102: #if defined(BOOST_NO_CXX11_CONSTEXPR) Chris@102: complex(const value_type& r = value_type(), Chris@102: const value_type& i = value_type()) : re(r), Chris@102: im(i) { } Chris@102: Chris@102: template Chris@102: complex(const complex& x) : re(x.real()), Chris@102: im(x.imag()) { } Chris@102: Chris@102: const value_type& real() const { return re; } Chris@102: const value_type& imag() const { return im; } Chris@102: Chris@102: value_type& real() { return re; } Chris@102: value_type& imag() { return im; } Chris@102: #else Chris@102: BOOST_CONSTEXPR complex(const value_type& r = value_type(), Chris@102: const value_type& i = value_type()) : re(r), Chris@102: im(i) { } Chris@102: Chris@102: template Chris@102: BOOST_CONSTEXPR complex(const complex& x) : re(x.real()), Chris@102: im(x.imag()) { } Chris@102: Chris@102: value_type real() const { return re; } Chris@102: value_type imag() const { return im; } Chris@102: #endif Chris@102: Chris@102: void real(value_type r) { re = r; } Chris@102: void imag(value_type i) { im = i; } Chris@102: Chris@102: complex& operator=(const value_type& v) Chris@102: { Chris@102: re = v; Chris@102: im = value_type(0); Chris@102: return *this; Chris@102: } Chris@102: Chris@102: complex& operator+=(const value_type& v) Chris@102: { Chris@102: re += v; Chris@102: return *this; Chris@102: } Chris@102: Chris@102: complex& operator-=(const value_type& v) Chris@102: { Chris@102: re -= v; Chris@102: return *this; Chris@102: } Chris@102: Chris@102: complex& operator*=(const value_type& v) Chris@102: { Chris@102: re *= v; Chris@102: im *= v; Chris@102: return *this; Chris@102: } Chris@102: Chris@102: complex& operator/=(const value_type& v) Chris@102: { Chris@102: re /= v; Chris@102: im /= v; Chris@102: return *this; Chris@102: } Chris@102: Chris@102: template Chris@102: complex& operator=(const complex& x) Chris@102: { Chris@102: re = x.real(); Chris@102: im = x.imag(); Chris@102: return *this; Chris@102: } Chris@102: Chris@102: template Chris@102: complex& operator+=(const complex& x) Chris@102: { Chris@102: re += x.real(); Chris@102: im += x.imag(); Chris@102: return *this; Chris@102: } Chris@102: Chris@102: template Chris@102: complex& operator-=(const complex& x) Chris@102: { Chris@102: re -= x.real(); Chris@102: im -= x.imag(); Chris@102: return *this; Chris@102: } Chris@102: Chris@102: template Chris@102: complex& operator*=(const complex& x) Chris@102: { Chris@102: const value_type tmp_real = (re * x.real()) - (im * x.imag()); Chris@102: im = (re * x.imag()) + (im * x.real()); Chris@102: re = tmp_real; Chris@102: return *this; Chris@102: } Chris@102: Chris@102: template Chris@102: complex& operator/=(const complex& x) Chris@102: { Chris@102: const value_type tmp_real = (re * x.real()) + (im * x.imag()); Chris@102: const value_type the_norm = std::norm(x); Chris@102: im = ((im * x.real()) - (re * x.imag())) / the_norm; Chris@102: re = tmp_real / the_norm; Chris@102: return *this; Chris@102: } Chris@102: Chris@102: private: Chris@102: value_type re; Chris@102: value_type im; Chris@102: }; Chris@102: Chris@102: // Constructors from built-in complex representation of floating-point types. Chris@102: complex::complex(const complex& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { } Chris@102: complex::complex(const complex& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { } Chris@102: complex::complex(const complex& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { } Chris@102: } // namespace std Chris@102: Chris@102: namespace boost { namespace math { namespace cstdfloat { namespace detail { Chris@102: template std::complex multiply_by_i(const std::complex& x) Chris@102: { Chris@102: // Multiply x (in C) by I (the imaginary component), and return the result. Chris@102: return std::complex(-x.imag(), x.real()); Chris@102: } Chris@102: } } } } // boost::math::cstdfloat::detail Chris@102: Chris@102: namespace std Chris@102: { Chris@102: // ISO/IEC 14882:2011, Section 26.4.7, specific values. Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex& x) { return x.real(); } Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex& x) { return x.imag(); } Chris@102: Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex& x) { using std::sqrt; return sqrt ((real(x) * real(x)) + (imag(x) * imag(x))); } Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex& x) { using std::atan2; return atan2(x.imag(), x.real()); } Chris@102: inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex& x) { return (real(x) * real(x)) + (imag(x) * imag(x)); } Chris@102: Chris@102: inline complex conj (const complex& x) { return complex(x.real(), -x.imag()); } Chris@102: Chris@102: inline complex proj (const complex& x) Chris@102: { Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE m = (std::numeric_limits::max)(); Chris@102: if ((x.real() > m) Chris@102: || (x.real() < -m) Chris@102: || (x.imag() > m) Chris@102: || (x.imag() < -m)) Chris@102: { Chris@102: // We have an infinity, return a normalized infinity, respecting the sign of the imaginary part: Chris@102: return complex(std::numeric_limits::infinity(), x.imag() < 0 ? -0 : 0); Chris@102: } Chris@102: return x; Chris@102: } Chris@102: Chris@102: inline complex polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& rho, Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& theta) Chris@102: { Chris@102: using std::sin; Chris@102: using std::cos; Chris@102: Chris@102: return complex(rho * cos(theta), rho * sin(theta)); Chris@102: } Chris@102: Chris@102: // Global add, sub, mul, div. Chris@102: inline complex operator+(const complex& u, const complex& v) { return complex(u.real() + v.real(), u.imag() + v.imag()); } Chris@102: inline complex operator-(const complex& u, const complex& v) { return complex(u.real() - v.real(), u.imag() - v.imag()); } Chris@102: Chris@102: inline complex operator*(const complex& u, const complex& v) Chris@102: { Chris@102: return complex((u.real() * v.real()) - (u.imag() * v.imag()), Chris@102: (u.real() * v.imag()) + (u.imag() * v.real())); Chris@102: } Chris@102: Chris@102: inline complex operator/(const complex& u, const complex& v) Chris@102: { Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE the_norm = std::norm(v); Chris@102: Chris@102: return complex(((u.real() * v.real()) + (u.imag() * v.imag())) / the_norm, Chris@102: ((u.imag() * v.real()) - (u.real() * v.imag())) / the_norm); Chris@102: } Chris@102: Chris@102: inline complex operator+(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() + v, u.imag()); } Chris@102: inline complex operator-(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() - v, u.imag()); } Chris@102: inline complex operator*(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() * v, u.imag() * v); } Chris@102: inline complex operator/(const complex& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex(u.real() / v, u.imag() / v); } Chris@102: Chris@102: inline complex operator+(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { return complex(u + v.real(), v.imag()); } Chris@102: inline complex operator-(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { return complex(u - v.real(), -v.imag()); } Chris@102: inline complex operator*(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { return complex(u * v.real(), u * v.imag()); } Chris@102: inline complex operator/(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex& v) { const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE v_norm = norm(v); return complex((u * v.real()) / v_norm, (-u * v.imag()) / v_norm); } Chris@102: Chris@102: // Unary plus / minus. Chris@102: inline complex operator+(const complex& u) { return u; } Chris@102: inline complex operator-(const complex& u) { return complex(-u.real(), -u.imag()); } Chris@102: Chris@102: // Equality and inequality. Chris@102: inline bool operator==(const complex& x, const complex& y) { return ((x.real() == y.real()) && (x.imag() == y.imag())); } Chris@102: inline bool operator==(const complex& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() == y) && (x.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } Chris@102: inline bool operator==(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex& y) { return ((x == y.real()) && (y.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } Chris@102: inline bool operator!=(const complex& x, const complex& y) { return ((x.real() != y.real()) || (x.imag() != y.imag())); } Chris@102: inline bool operator!=(const complex& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() != y) || (x.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } Chris@102: inline bool operator!=(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex& y) { return ((x != y.real()) || (y.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } Chris@102: Chris@102: // ISO/IEC 14882:2011, Section 26.4.8, transcendentals. Chris@102: inline complex sqrt(const complex& x) Chris@102: { Chris@102: using std::fabs; Chris@102: using std::sqrt; Chris@102: Chris@102: // Compute sqrt(x) for x in C: Chris@102: // sqrt(x) = (s , xi / 2s) : for xr > 0, Chris@102: // (|xi| / 2s, +-s) : for xr < 0, Chris@102: // (sqrt(xi), sqrt(xi) : for xr = 0, Chris@102: // where s = sqrt{ [ |xr| + sqrt(xr^2 + xi^2) ] / 2 }, Chris@102: // and the +- sign is the same as the sign of xi. Chris@102: Chris@102: if(x.real() > 0) Chris@102: { Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2); Chris@102: Chris@102: return complex(s, x.imag() / (s * 2)); Chris@102: } Chris@102: else if(x.real() < 0) Chris@102: { Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2); Chris@102: Chris@102: const bool imag_is_neg = (x.imag() < 0); Chris@102: Chris@102: return complex(fabs(x.imag()) / (s * 2), (imag_is_neg ? -s : s)); Chris@102: } Chris@102: else Chris@102: { Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sqrt_xi_half = sqrt(x.imag() / 2); Chris@102: Chris@102: return complex(sqrt_xi_half, sqrt_xi_half); Chris@102: } Chris@102: } Chris@102: Chris@102: inline complex sin(const complex& x) Chris@102: { Chris@102: using std::sin; Chris@102: using std::cos; Chris@102: using std::exp; Chris@102: Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; Chris@102: Chris@102: return complex(sin_x * cosh_y, cos_x * sinh_y); Chris@102: } Chris@102: Chris@102: inline complex cos(const complex& x) Chris@102: { Chris@102: using std::sin; Chris@102: using std::cos; Chris@102: using std::exp; Chris@102: Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; Chris@102: Chris@102: return complex(cos_x * cosh_y, -(sin_x * sinh_y)); Chris@102: } Chris@102: Chris@102: inline complex tan(const complex& x) Chris@102: { Chris@102: using std::sin; Chris@102: using std::cos; Chris@102: using std::exp; Chris@102: Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; Chris@102: Chris@102: return ( complex(sin_x * cosh_y, cos_x * sinh_y) Chris@102: / complex(cos_x * cosh_y, -sin_x * sinh_y)); Chris@102: } Chris@102: Chris@102: inline complex asin(const complex& x) Chris@102: { Chris@102: return -boost::math::cstdfloat::detail::multiply_by_i(std::log(boost::math::cstdfloat::detail::multiply_by_i(x) + std::sqrt(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - (x * x)))); Chris@102: } Chris@102: Chris@102: inline complex acos(const complex& x) Chris@102: { Chris@102: return boost::math::constants::half_pi() - std::asin(x); Chris@102: } Chris@102: Chris@102: inline complex atan(const complex& x) Chris@102: { Chris@102: const complex izz = boost::math::cstdfloat::detail::multiply_by_i(x); Chris@102: Chris@102: return boost::math::cstdfloat::detail::multiply_by_i(std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - izz) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + izz)) / 2; Chris@102: } Chris@102: Chris@102: inline complex exp(const complex& x) Chris@102: { Chris@102: using std::exp; Chris@102: Chris@102: return std::polar(exp(x.real()), x.imag()); Chris@102: } Chris@102: Chris@102: inline complex log(const complex& x) Chris@102: { Chris@102: using std::atan2; Chris@102: using std::log; Chris@102: Chris@102: return complex(log(std::norm(x)) / 2, atan2(x.imag(), x.real())); Chris@102: } Chris@102: Chris@102: inline complex log10(const complex& x) Chris@102: { Chris@102: return std::log(x) / boost::math::constants::ln_ten(); Chris@102: } Chris@102: Chris@102: inline complex pow(const complex& x, Chris@102: int p) Chris@102: { Chris@102: const bool re_isneg = (x.real() < 0); Chris@102: const bool re_isnan = (x.real() != x.real()); Chris@102: const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits::max)()) Chris@102: : bool(-x.real() > (std::numeric_limits::max)())); Chris@102: Chris@102: const bool im_isneg = (x.imag() < 0); Chris@102: const bool im_isnan = (x.imag() != x.imag()); Chris@102: const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits::max)()) Chris@102: : bool(-x.imag() > (std::numeric_limits::max)())); Chris@102: Chris@102: if(re_isnan || im_isnan) { return x; } Chris@102: Chris@102: if(re_isinf || im_isinf) Chris@102: { Chris@102: return complex(std::numeric_limits::quiet_NaN(), Chris@102: std::numeric_limits::quiet_NaN()); Chris@102: } Chris@102: Chris@102: if(p < 0) Chris@102: { Chris@102: if(std::abs(x) < (std::numeric_limits::min)()) Chris@102: { Chris@102: return complex(std::numeric_limits::infinity(), Chris@102: std::numeric_limits::infinity()); Chris@102: } Chris@102: else Chris@102: { Chris@102: return BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / std::pow(x, -p); Chris@102: } Chris@102: } Chris@102: Chris@102: if(p == 0) Chris@102: { Chris@102: return complex(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)); Chris@102: } Chris@102: else Chris@102: { Chris@102: if(p == 1) { return x; } Chris@102: Chris@102: if(std::abs(x) > (std::numeric_limits::max)()) Chris@102: { Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE re = (re_isneg ? -std::numeric_limits::infinity() Chris@102: : +std::numeric_limits::infinity()); Chris@102: Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE im = (im_isneg ? -std::numeric_limits::infinity() Chris@102: : +std::numeric_limits::infinity()); Chris@102: Chris@102: return complex(re, im); Chris@102: } Chris@102: Chris@102: if (p == 2) { return (x * x); } Chris@102: else if(p == 3) { return ((x * x) * x); } Chris@102: else if(p == 4) { const complex x2 = (x * x); return (x2 * x2); } Chris@102: else Chris@102: { Chris@102: // The variable xn stores the binary powers of x. Chris@102: complex result(((p % 2) != 0) ? x : complex(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1))); Chris@102: complex xn (x); Chris@102: Chris@102: int p2 = p; Chris@102: Chris@102: while((p2 /= 2) != 0) Chris@102: { Chris@102: // Square xn for each binary power. Chris@102: xn *= xn; Chris@102: Chris@102: const bool has_binary_power = ((p2 % 2) != 0); Chris@102: Chris@102: if(has_binary_power) Chris@102: { Chris@102: // Multiply the result with each binary power contained in the exponent. Chris@102: result *= xn; Chris@102: } Chris@102: } Chris@102: Chris@102: return result; Chris@102: } Chris@102: } Chris@102: } Chris@102: Chris@102: inline complex pow(const complex& x, Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& a) Chris@102: { Chris@102: return std::exp(a * std::log(x)); Chris@102: } Chris@102: Chris@102: inline complex pow(const complex& x, Chris@102: const complex& a) Chris@102: { Chris@102: return std::exp(a * std::log(x)); Chris@102: } Chris@102: Chris@102: inline complex pow(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, Chris@102: const complex& a) Chris@102: { Chris@102: return std::exp(a * std::log(x)); Chris@102: } Chris@102: Chris@102: inline complex sinh(const complex& x) Chris@102: { Chris@102: using std::sin; Chris@102: using std::cos; Chris@102: using std::exp; Chris@102: Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2; Chris@102: Chris@102: return complex(cos_y * sinh_x, cosh_x * sin_y); Chris@102: } Chris@102: Chris@102: inline complex cosh(const complex& x) Chris@102: { Chris@102: using std::sin; Chris@102: using std::cos; Chris@102: using std::exp; Chris@102: Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real()); Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2; Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2; Chris@102: Chris@102: return complex(cos_y * cosh_x, sin_y * sinh_x); Chris@102: } Chris@102: Chris@102: inline complex tanh(const complex& x) Chris@102: { Chris@102: const complex ex_plus = std::exp(x); Chris@102: const complex ex_minus = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / ex_plus; Chris@102: Chris@102: return (ex_plus - ex_minus) / (ex_plus + ex_minus); Chris@102: } Chris@102: Chris@102: inline complex asinh(const complex& x) Chris@102: { Chris@102: return std::log(x + std::sqrt((x * x) + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1))); Chris@102: } Chris@102: Chris@102: inline complex acosh(const complex& x) Chris@102: { Chris@102: const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE my_one(1); Chris@102: Chris@102: const complex zp(x.real() + my_one, x.imag()); Chris@102: const complex zm(x.real() - my_one, x.imag()); Chris@102: Chris@102: return std::log(x + (zp * std::sqrt(zm / zp))); Chris@102: } Chris@102: Chris@102: inline complex atanh(const complex& x) Chris@102: { Chris@102: return (std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + x) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - x)) / 2.0; Chris@102: } Chris@102: Chris@102: template Chris@102: inline std::basic_ostream& operator<<(std::basic_ostream& os, const std::complex& x) Chris@102: { Chris@102: std::basic_ostringstream ostr; Chris@102: Chris@102: ostr.flags(os.flags()); Chris@102: ostr.imbue(os.getloc()); Chris@102: ostr.precision(os.precision()); Chris@102: Chris@102: ostr << char_type('(') Chris@102: << x.real() Chris@102: << char_type(',') Chris@102: << x.imag() Chris@102: << char_type(')'); Chris@102: Chris@102: return (os << ostr.str()); Chris@102: } Chris@102: Chris@102: template Chris@102: inline std::basic_istream& operator>>(std::basic_istream& is, std::complex& x) Chris@102: { Chris@102: BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE rx; Chris@102: BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE ix; Chris@102: Chris@102: char_type the_char; Chris@102: Chris@102: static_cast(is >> the_char); Chris@102: Chris@102: if(the_char == static_cast('(')) Chris@102: { Chris@102: static_cast(is >> rx >> the_char); Chris@102: Chris@102: if(the_char == static_cast(',')) Chris@102: { Chris@102: static_cast(is >> ix >> the_char); Chris@102: Chris@102: if(the_char == static_cast(')')) Chris@102: { Chris@102: x = complex(rx, ix); Chris@102: } Chris@102: else Chris@102: { Chris@102: is.setstate(ios_base::failbit); Chris@102: } Chris@102: } Chris@102: else if(the_char == static_cast(')')) Chris@102: { Chris@102: x = rx; Chris@102: } Chris@102: else Chris@102: { Chris@102: is.setstate(ios_base::failbit); Chris@102: } Chris@102: } Chris@102: else Chris@102: { Chris@102: static_cast(is.putback(the_char)); Chris@102: Chris@102: static_cast(is >> rx); Chris@102: Chris@102: x = rx; Chris@102: } Chris@102: Chris@102: return is; Chris@102: } Chris@102: } // namespace std Chris@102: Chris@102: #endif // _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_