]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright Christopher Kormanyos 2014. | |
3 | // Copyright John Maddock 2014. | |
4 | // Copyright Paul Bristow 2014. | |
5 | // Distributed under the Boost Software License, | |
6 | // Version 1.0. (See accompanying file LICENSE_1_0.txt | |
7 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | // | |
9 | ||
10 | // Implement a specialization of std::complex<> for *anything* that | |
11 | // is defined as BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE. | |
12 | ||
f67539c2 TL |
13 | #ifndef BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ |
14 | #define BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ | |
7c673cae FG |
15 | |
16 | #if defined(__GNUC__) | |
17 | #pragma GCC system_header | |
18 | #endif | |
19 | ||
20 | #include <complex> | |
21 | #include <boost/math/constants/constants.hpp> | |
f67539c2 | 22 | #include <boost/math/tools/cxx03_warn.hpp> |
7c673cae FG |
23 | |
24 | namespace std | |
25 | { | |
26 | // Forward declarations. | |
27 | template<class float_type> | |
28 | class complex; | |
29 | ||
30 | template<> | |
31 | class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>; | |
32 | ||
33 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
34 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
35 | ||
36 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
37 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
38 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
39 | ||
40 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
41 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
42 | ||
43 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&, | |
44 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& = 0); | |
45 | ||
46 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
47 | ||
48 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
49 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
50 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
51 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
52 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
53 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
54 | ||
55 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
56 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
57 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
58 | ||
59 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&, | |
60 | int); | |
61 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&, | |
62 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&); | |
63 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&, | |
64 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
65 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&, | |
66 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
67 | ||
68 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
69 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
70 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
71 | ||
72 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
73 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
74 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
75 | ||
76 | template<class char_type, class traits_type> | |
77 | inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>&, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
78 | ||
79 | template<class char_type, class traits_type> | |
80 | inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>&, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&); | |
81 | ||
82 | // Template specialization of the complex class. | |
83 | template<> | |
84 | class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
85 | { | |
86 | public: | |
87 | typedef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE value_type; | |
88 | ||
20effc67 TL |
89 | complex(const complex<float>&); |
90 | complex(const complex<double>&); | |
91 | complex(const complex<long double>&); | |
7c673cae FG |
92 | |
93 | #if defined(BOOST_NO_CXX11_CONSTEXPR) | |
94 | complex(const value_type& r = value_type(), | |
95 | const value_type& i = value_type()) : re(r), | |
96 | im(i) { } | |
97 | ||
98 | template<typename X> | |
20effc67 | 99 | explicit complex(const complex<X>& x) : re(x.real()), |
1e59de90 | 100 | im(x.imag()) { } |
7c673cae FG |
101 | |
102 | const value_type& real() const { return re; } | |
103 | const value_type& imag() const { return im; } | |
104 | ||
105 | value_type& real() { return re; } | |
106 | value_type& imag() { return im; } | |
107 | #else | |
1e59de90 TL |
108 | constexpr complex(const value_type& r = value_type(), |
109 | const value_type& i = value_type()) : re(r), | |
110 | im(i) { } | |
7c673cae FG |
111 | |
112 | template<typename X> | |
1e59de90 TL |
113 | explicit constexpr complex(const complex<X>& x) : re(x.real()), |
114 | im(x.imag()) { } | |
7c673cae FG |
115 | |
116 | value_type real() const { return re; } | |
117 | value_type imag() const { return im; } | |
118 | #endif | |
119 | ||
120 | void real(value_type r) { re = r; } | |
121 | void imag(value_type i) { im = i; } | |
122 | ||
123 | complex<value_type>& operator=(const value_type& v) | |
124 | { | |
125 | re = v; | |
126 | im = value_type(0); | |
127 | return *this; | |
128 | } | |
129 | ||
130 | complex<value_type>& operator+=(const value_type& v) | |
131 | { | |
132 | re += v; | |
133 | return *this; | |
134 | } | |
135 | ||
136 | complex<value_type>& operator-=(const value_type& v) | |
137 | { | |
138 | re -= v; | |
139 | return *this; | |
140 | } | |
141 | ||
142 | complex<value_type>& operator*=(const value_type& v) | |
143 | { | |
144 | re *= v; | |
145 | im *= v; | |
146 | return *this; | |
147 | } | |
148 | ||
149 | complex<value_type>& operator/=(const value_type& v) | |
150 | { | |
151 | re /= v; | |
152 | im /= v; | |
153 | return *this; | |
154 | } | |
155 | ||
156 | template<typename X> | |
157 | complex<value_type>& operator=(const complex<X>& x) | |
158 | { | |
159 | re = x.real(); | |
160 | im = x.imag(); | |
161 | return *this; | |
162 | } | |
163 | ||
164 | template<typename X> | |
165 | complex<value_type>& operator+=(const complex<X>& x) | |
166 | { | |
167 | re += x.real(); | |
168 | im += x.imag(); | |
169 | return *this; | |
170 | } | |
171 | ||
172 | template<typename X> | |
173 | complex<value_type>& operator-=(const complex<X>& x) | |
174 | { | |
175 | re -= x.real(); | |
176 | im -= x.imag(); | |
177 | return *this; | |
178 | } | |
179 | ||
180 | template<typename X> | |
181 | complex<value_type>& operator*=(const complex<X>& x) | |
182 | { | |
183 | const value_type tmp_real = (re * x.real()) - (im * x.imag()); | |
184 | im = (re * x.imag()) + (im * x.real()); | |
185 | re = tmp_real; | |
186 | return *this; | |
187 | } | |
188 | ||
189 | template<typename X> | |
190 | complex<value_type>& operator/=(const complex<X>& x) | |
191 | { | |
192 | const value_type tmp_real = (re * x.real()) + (im * x.imag()); | |
193 | const value_type the_norm = std::norm(x); | |
194 | im = ((im * x.real()) - (re * x.imag())) / the_norm; | |
195 | re = tmp_real / the_norm; | |
196 | return *this; | |
197 | } | |
198 | ||
199 | private: | |
200 | value_type re; | |
201 | value_type im; | |
202 | }; | |
203 | ||
204 | // Constructors from built-in complex representation of floating-point types. | |
205 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<float>& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { } | |
206 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<double>& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { } | |
207 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<long double>& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { } | |
208 | } // namespace std | |
209 | ||
210 | namespace boost { namespace math { namespace cstdfloat { namespace detail { | |
211 | template<class float_type> inline std::complex<float_type> multiply_by_i(const std::complex<float_type>& x) | |
212 | { | |
213 | // Multiply x (in C) by I (the imaginary component), and return the result. | |
214 | return std::complex<float_type>(-x.imag(), x.real()); | |
215 | } | |
216 | } } } } // boost::math::cstdfloat::detail | |
217 | ||
218 | namespace std | |
219 | { | |
220 | // ISO/IEC 14882:2011, Section 26.4.7, specific values. | |
221 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.real(); } | |
222 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.imag(); } | |
223 | ||
224 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::sqrt; return sqrt ((real(x) * real(x)) + (imag(x) * imag(x))); } | |
225 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::atan2; return atan2(x.imag(), x.real()); } | |
226 | inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return (real(x) * real(x)) + (imag(x) * imag(x)); } | |
227 | ||
228 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(x.real(), -x.imag()); } | |
229 | ||
230 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
231 | { | |
232 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE m = (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)(); | |
1e59de90 TL |
233 | if ( (x.real() > m) |
234 | || (x.real() < -m) | |
235 | || (x.imag() > m) | |
236 | || (x.imag() < -m)) | |
7c673cae FG |
237 | { |
238 | // We have an infinity, return a normalized infinity, respecting the sign of the imaginary part: | |
239 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), x.imag() < 0 ? -0 : 0); | |
240 | } | |
241 | return x; | |
242 | } | |
243 | ||
244 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& rho, | |
245 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& theta) | |
246 | { | |
247 | using std::sin; | |
248 | using std::cos; | |
249 | ||
250 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rho * cos(theta), rho * sin(theta)); | |
251 | } | |
252 | ||
253 | // Global add, sub, mul, div. | |
254 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v.real(), u.imag() + v.imag()); } | |
255 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v.real(), u.imag() - v.imag()); } | |
256 | ||
257 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) | |
258 | { | |
259 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u.real() * v.real()) - (u.imag() * v.imag()), | |
260 | (u.real() * v.imag()) + (u.imag() * v.real())); | |
261 | } | |
262 | ||
263 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) | |
264 | { | |
265 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE the_norm = std::norm(v); | |
266 | ||
267 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(((u.real() * v.real()) + (u.imag() * v.imag())) / the_norm, | |
268 | ((u.imag() * v.real()) - (u.real() * v.imag())) / the_norm); | |
269 | } | |
270 | ||
271 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v, u.imag()); } | |
272 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v, u.imag()); } | |
273 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() * v, u.imag() * v); } | |
274 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() / v, u.imag() / v); } | |
275 | ||
276 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u + v.real(), v.imag()); } | |
277 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u - v.real(), -v.imag()); } | |
278 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u * v.real(), u * v.imag()); } | |
279 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE v_norm = norm(v); return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u * v.real()) / v_norm, (-u * v.imag()) / v_norm); } | |
280 | ||
281 | // Unary plus / minus. | |
282 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return u; } | |
283 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(-u.real(), -u.imag()); } | |
284 | ||
285 | // Equality and inequality. | |
286 | inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() == y.real()) && (x.imag() == y.imag())); } | |
287 | inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() == y) && (x.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } | |
288 | inline bool operator==(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x == y.real()) && (y.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } | |
289 | inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() != y.real()) || (x.imag() != y.imag())); } | |
290 | inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() != y) || (x.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } | |
291 | inline bool operator!=(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x != y.real()) || (y.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); } | |
292 | ||
293 | // ISO/IEC 14882:2011, Section 26.4.8, transcendentals. | |
294 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
295 | { | |
296 | using std::fabs; | |
297 | using std::sqrt; | |
298 | ||
299 | // Compute sqrt(x) for x in C: | |
300 | // sqrt(x) = (s , xi / 2s) : for xr > 0, | |
301 | // (|xi| / 2s, +-s) : for xr < 0, | |
302 | // (sqrt(xi), sqrt(xi) : for xr = 0, | |
303 | // where s = sqrt{ [ |xr| + sqrt(xr^2 + xi^2) ] / 2 }, | |
304 | // and the +- sign is the same as the sign of xi. | |
305 | ||
306 | if(x.real() > 0) | |
307 | { | |
308 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2); | |
309 | ||
310 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(s, x.imag() / (s * 2)); | |
311 | } | |
312 | else if(x.real() < 0) | |
313 | { | |
314 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2); | |
315 | ||
316 | const bool imag_is_neg = (x.imag() < 0); | |
317 | ||
318 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(fabs(x.imag()) / (s * 2), (imag_is_neg ? -s : s)); | |
319 | } | |
320 | else | |
321 | { | |
322 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sqrt_xi_half = sqrt(x.imag() / 2); | |
323 | ||
324 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sqrt_xi_half, sqrt_xi_half); | |
325 | } | |
326 | } | |
327 | ||
328 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
329 | { | |
330 | using std::sin; | |
331 | using std::cos; | |
332 | using std::exp; | |
333 | ||
334 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); | |
335 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); | |
336 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); | |
337 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; | |
338 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; | |
339 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; | |
340 | ||
341 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y); | |
342 | } | |
343 | ||
344 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
345 | { | |
346 | using std::sin; | |
347 | using std::cos; | |
348 | using std::exp; | |
349 | ||
350 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); | |
351 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); | |
352 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); | |
353 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; | |
354 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; | |
355 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; | |
356 | ||
357 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -(sin_x * sinh_y)); | |
358 | } | |
359 | ||
360 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
361 | { | |
362 | using std::sin; | |
363 | using std::cos; | |
364 | using std::exp; | |
365 | ||
366 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real()); | |
367 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real()); | |
368 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag()); | |
369 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp; | |
370 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2; | |
371 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2; | |
372 | ||
373 | return ( complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y) | |
374 | / complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -sin_x * sinh_y)); | |
375 | } | |
376 | ||
377 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
378 | { | |
379 | 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)))); | |
380 | } | |
381 | ||
382 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
383 | { | |
384 | return boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>() - std::asin(x); | |
385 | } | |
386 | ||
387 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
388 | { | |
389 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> izz = boost::math::cstdfloat::detail::multiply_by_i(x); | |
390 | ||
391 | 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; | |
392 | } | |
393 | ||
394 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
395 | { | |
396 | using std::exp; | |
397 | ||
398 | return std::polar(exp(x.real()), x.imag()); | |
399 | } | |
400 | ||
401 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
402 | { | |
403 | using std::atan2; | |
404 | using std::log; | |
405 | ||
1e59de90 TL |
406 | const bool re_isneg = (x.real() < 0); |
407 | const bool re_isnan = (x.real() != x.real()); | |
408 | const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
409 | : bool(-x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())); | |
410 | ||
411 | const bool im_isneg = (x.imag() < 0); | |
412 | const bool im_isnan = (x.imag() != x.imag()); | |
413 | const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
414 | : bool(-x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())); | |
415 | ||
416 | if(re_isnan || im_isnan) { return x; } | |
417 | ||
418 | if(re_isinf || im_isinf) | |
419 | { | |
420 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), | |
421 | BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0.0)); | |
422 | } | |
423 | ||
424 | const bool re_iszero = ((re_isneg || (x.real() > 0)) == false); | |
425 | ||
426 | if(re_iszero) | |
427 | { | |
428 | const bool im_iszero = ((im_isneg || (x.imag() > 0)) == false); | |
429 | ||
430 | if(im_iszero) | |
431 | { | |
432 | return std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
433 | ( | |
434 | -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), | |
435 | BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0.0) | |
436 | ); | |
437 | } | |
438 | else | |
439 | { | |
440 | if(im_isneg == false) | |
441 | { | |
442 | return std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
443 | ( | |
444 | log(x.imag()), | |
445 | boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>() | |
446 | ); | |
447 | } | |
448 | else | |
449 | { | |
450 | return std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
451 | ( | |
452 | log(-x.imag()), | |
453 | -boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>() | |
454 | ); | |
455 | } | |
456 | } | |
457 | } | |
458 | else | |
459 | { | |
460 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(log(std::norm(x)) / 2, atan2(x.imag(), x.real())); | |
461 | } | |
7c673cae FG |
462 | } |
463 | ||
464 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
465 | { | |
466 | return std::log(x) / boost::math::constants::ln_ten<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(); | |
467 | } | |
468 | ||
469 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, | |
470 | int p) | |
471 | { | |
472 | const bool re_isneg = (x.real() < 0); | |
473 | const bool re_isnan = (x.real() != x.real()); | |
474 | const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
475 | : bool(-x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())); | |
476 | ||
477 | const bool im_isneg = (x.imag() < 0); | |
478 | const bool im_isnan = (x.imag() != x.imag()); | |
479 | const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
480 | : bool(-x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())); | |
481 | ||
482 | if(re_isnan || im_isnan) { return x; } | |
483 | ||
484 | if(re_isinf || im_isinf) | |
485 | { | |
486 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(), | |
487 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN()); | |
488 | } | |
489 | ||
490 | if(p < 0) | |
491 | { | |
492 | if(std::abs(x) < (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::min)()) | |
493 | { | |
494 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), | |
495 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()); | |
496 | } | |
497 | else | |
498 | { | |
499 | return BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / std::pow(x, -p); | |
500 | } | |
501 | } | |
502 | ||
503 | if(p == 0) | |
504 | { | |
505 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)); | |
506 | } | |
507 | else | |
508 | { | |
509 | if(p == 1) { return x; } | |
510 | ||
511 | if(std::abs(x) > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
512 | { | |
513 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE re = (re_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity() | |
514 | : +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()); | |
515 | ||
516 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE im = (im_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity() | |
517 | : +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()); | |
518 | ||
519 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(re, im); | |
520 | } | |
521 | ||
522 | if (p == 2) { return (x * x); } | |
523 | else if(p == 3) { return ((x * x) * x); } | |
524 | else if(p == 4) { const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> x2 = (x * x); return (x2 * x2); } | |
525 | else | |
526 | { | |
527 | // The variable xn stores the binary powers of x. | |
528 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> result(((p % 2) != 0) ? x : complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1))); | |
529 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> xn (x); | |
530 | ||
531 | int p2 = p; | |
532 | ||
533 | while((p2 /= 2) != 0) | |
534 | { | |
535 | // Square xn for each binary power. | |
536 | xn *= xn; | |
537 | ||
538 | const bool has_binary_power = ((p2 % 2) != 0); | |
539 | ||
540 | if(has_binary_power) | |
541 | { | |
542 | // Multiply the result with each binary power contained in the exponent. | |
543 | result *= xn; | |
544 | } | |
545 | } | |
546 | ||
547 | return result; | |
548 | } | |
549 | } | |
550 | } | |
551 | ||
552 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, | |
553 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& a) | |
554 | { | |
1e59de90 TL |
555 | const bool x_im_isneg = (x.imag() < 0); |
556 | const bool x_im_iszero = ((x_im_isneg || (x.imag() > 0)) == false); | |
557 | ||
558 | if(x_im_iszero) | |
559 | { | |
560 | using std::pow; | |
561 | ||
562 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE pxa = pow(x.real(), a); | |
563 | ||
564 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(pxa, BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0)); | |
565 | } | |
566 | else | |
567 | { | |
568 | return std::exp(a * std::log(x)); | |
569 | } | |
7c673cae FG |
570 | } |
571 | ||
572 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, | |
573 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a) | |
574 | { | |
1e59de90 TL |
575 | const bool x_im_isneg = (x.imag() < 0); |
576 | const bool x_im_iszero = ((x_im_isneg || (x.imag() > 0)) == false); | |
577 | ||
578 | if(x_im_iszero) | |
579 | { | |
580 | using std::pow; | |
581 | ||
582 | return pow(x.real(), a); | |
583 | } | |
584 | else | |
585 | { | |
586 | return std::exp(a * std::log(x)); | |
587 | } | |
7c673cae FG |
588 | } |
589 | ||
590 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, | |
591 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a) | |
592 | { | |
1e59de90 TL |
593 | const bool x_isneg = (x < 0); |
594 | const bool x_isnan = (x != x); | |
595 | const bool x_isinf = ((!x_isneg) ? bool(+x > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
596 | : bool(-x > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())); | |
597 | ||
598 | const bool a_re_isneg = (a.real() < 0); | |
599 | const bool a_re_isnan = (a.real() != a.real()); | |
600 | const bool a_re_isinf = ((!a_re_isneg) ? bool(+a.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
601 | : bool(-a.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())); | |
602 | ||
603 | const bool a_im_isneg = (a.imag() < 0); | |
604 | const bool a_im_isnan = (a.imag() != a.imag()); | |
605 | const bool a_im_isinf = ((!a_im_isneg) ? bool(+a.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()) | |
606 | : bool(-a.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())); | |
607 | ||
608 | const bool args_is_nan = (x_isnan || a_re_isnan || a_im_isnan); | |
609 | const bool a_is_finite = (!(a_re_isnan || a_re_isinf || a_im_isnan || a_im_isinf)); | |
610 | ||
611 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> result; | |
612 | ||
613 | if(args_is_nan) | |
614 | { | |
615 | result = | |
616 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
617 | ( | |
618 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(), | |
619 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN() | |
620 | ); | |
621 | } | |
622 | else if(x_isinf) | |
623 | { | |
624 | if(a_is_finite) | |
625 | { | |
626 | result = | |
627 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
628 | ( | |
629 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), | |
630 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity() | |
631 | ); | |
632 | } | |
633 | else | |
634 | { | |
635 | result = | |
636 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
637 | ( | |
638 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(), | |
639 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN() | |
640 | ); | |
641 | } | |
642 | } | |
643 | else if(x > 0) | |
644 | { | |
645 | result = std::exp(a * std::log(x)); | |
646 | } | |
647 | else if(x < 0) | |
648 | { | |
649 | using std::acos; | |
650 | using std::log; | |
651 | ||
652 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
653 | cpx_lg_x | |
654 | ( | |
655 | log(-x), | |
656 | acos(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(-1)) | |
657 | ); | |
658 | ||
659 | result = std::exp(a * cpx_lg_x); | |
660 | } | |
661 | else | |
662 | { | |
663 | if(a_is_finite) | |
664 | { | |
665 | result = | |
666 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
667 | ( | |
668 | BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0), | |
669 | BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0) | |
670 | ); | |
671 | } | |
672 | else | |
673 | { | |
674 | result = | |
675 | complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> | |
676 | ( | |
677 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(), | |
678 | std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN() | |
679 | ); | |
680 | } | |
681 | } | |
682 | ||
683 | return result; | |
7c673cae FG |
684 | } |
685 | ||
686 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
687 | { | |
688 | using std::sin; | |
689 | using std::cos; | |
690 | using std::exp; | |
691 | ||
692 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag()); | |
693 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag()); | |
694 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real()); | |
695 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp; | |
696 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2; | |
697 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2; | |
698 | ||
699 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * sinh_x, cosh_x * sin_y); | |
700 | } | |
701 | ||
702 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
703 | { | |
704 | using std::sin; | |
705 | using std::cos; | |
706 | using std::exp; | |
707 | ||
708 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag()); | |
709 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag()); | |
710 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real()); | |
711 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp; | |
712 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2; | |
713 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2; | |
714 | ||
715 | return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * cosh_x, sin_y * sinh_x); | |
716 | } | |
717 | ||
718 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
719 | { | |
720 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_plus = std::exp(x); | |
721 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_minus = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / ex_plus; | |
722 | ||
723 | return (ex_plus - ex_minus) / (ex_plus + ex_minus); | |
724 | } | |
725 | ||
726 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
727 | { | |
728 | return std::log(x + std::sqrt((x * x) + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1))); | |
729 | } | |
730 | ||
731 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
732 | { | |
733 | const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE my_one(1); | |
734 | ||
735 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zp(x.real() + my_one, x.imag()); | |
736 | const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zm(x.real() - my_one, x.imag()); | |
737 | ||
738 | return std::log(x + (zp * std::sqrt(zm / zp))); | |
739 | } | |
740 | ||
741 | inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
742 | { | |
743 | return (std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + x) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - x)) / 2.0; | |
744 | } | |
745 | ||
746 | template<class char_type, class traits_type> | |
747 | inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
748 | { | |
749 | std::basic_ostringstream<char_type, traits_type> ostr; | |
750 | ||
751 | ostr.flags(os.flags()); | |
752 | ostr.imbue(os.getloc()); | |
753 | ostr.precision(os.precision()); | |
754 | ||
755 | ostr << char_type('(') | |
756 | << x.real() | |
757 | << char_type(',') | |
758 | << x.imag() | |
759 | << char_type(')'); | |
760 | ||
761 | return (os << ostr.str()); | |
762 | } | |
763 | ||
764 | template<class char_type, class traits_type> | |
765 | inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) | |
766 | { | |
767 | BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE rx; | |
768 | BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE ix; | |
769 | ||
770 | char_type the_char; | |
771 | ||
772 | static_cast<void>(is >> the_char); | |
773 | ||
774 | if(the_char == static_cast<char_type>('(')) | |
775 | { | |
776 | static_cast<void>(is >> rx >> the_char); | |
777 | ||
778 | if(the_char == static_cast<char_type>(',')) | |
779 | { | |
780 | static_cast<void>(is >> ix >> the_char); | |
781 | ||
782 | if(the_char == static_cast<char_type>(')')) | |
783 | { | |
784 | x = complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rx, ix); | |
785 | } | |
786 | else | |
787 | { | |
788 | is.setstate(ios_base::failbit); | |
789 | } | |
790 | } | |
791 | else if(the_char == static_cast<char_type>(')')) | |
792 | { | |
793 | x = rx; | |
794 | } | |
795 | else | |
796 | { | |
797 | is.setstate(ios_base::failbit); | |
798 | } | |
799 | } | |
800 | else | |
801 | { | |
802 | static_cast<void>(is.putback(the_char)); | |
803 | ||
804 | static_cast<void>(is >> rx); | |
805 | ||
806 | x = rx; | |
807 | } | |
808 | ||
809 | return is; | |
810 | } | |
811 | } // namespace std | |
812 | ||
f67539c2 | 813 | #endif // BOOST_MATH_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_ |