]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright 2018 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #ifndef BOOST_MULTIPRECISION_MPC_HPP | |
7 | #define BOOST_MULTIPRECISION_MPC_HPP | |
8 | ||
9 | #include <boost/multiprecision/number.hpp> | |
10 | #include <boost/cstdint.hpp> | |
11 | #include <boost/multiprecision/detail/digits.hpp> | |
f67539c2 | 12 | #include <boost/multiprecision/detail/atomic.hpp> |
92f5a8d4 TL |
13 | #include <boost/multiprecision/traits/is_variable_precision.hpp> |
14 | #include <boost/multiprecision/mpfr.hpp> | |
15 | #include <boost/multiprecision/logged_adaptor.hpp> | |
16 | #include <boost/functional/hash_fwd.hpp> | |
17 | #include <mpc.h> | |
18 | #include <cmath> | |
19 | #include <algorithm> | |
20 | #include <complex> | |
21 | ||
22 | #ifndef BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION | |
23 | #define BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION 20 | |
24 | #endif | |
25 | ||
26 | namespace boost { | |
27 | namespace multiprecision { | |
28 | namespace backends { | |
29 | ||
30 | template <unsigned digits10> | |
31 | struct mpc_complex_backend; | |
32 | ||
33 | } // namespace backends | |
34 | ||
35 | template <unsigned digits10> | |
36 | struct number_category<backends::mpc_complex_backend<digits10> > : public mpl::int_<number_kind_complex> | |
37 | {}; | |
38 | ||
39 | namespace backends { | |
40 | ||
41 | namespace detail { | |
42 | ||
43 | inline void mpc_copy_precision(mpc_t dest, const mpc_t src) | |
44 | { | |
45 | mpfr_prec_t p_dest = mpc_get_prec(dest); | |
46 | mpfr_prec_t p_src = mpc_get_prec(src); | |
47 | if (p_dest != p_src) | |
48 | mpc_set_prec(dest, p_src); | |
49 | } | |
50 | inline void mpc_copy_precision(mpc_t dest, const mpc_t src1, const mpc_t src2) | |
51 | { | |
52 | mpfr_prec_t p_dest = mpc_get_prec(dest); | |
53 | mpfr_prec_t p_src1 = mpc_get_prec(src1); | |
54 | mpfr_prec_t p_src2 = mpc_get_prec(src2); | |
55 | if (p_src2 > p_src1) | |
56 | p_src1 = p_src2; | |
57 | if (p_dest != p_src1) | |
58 | mpc_set_prec(dest, p_src1); | |
59 | } | |
60 | ||
61 | template <unsigned digits10> | |
62 | struct mpc_complex_imp | |
63 | { | |
64 | #ifdef BOOST_HAS_LONG_LONG | |
65 | typedef mpl::list<long, boost::long_long_type> signed_types; | |
66 | typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types; | |
67 | #else | |
68 | typedef mpl::list<long> signed_types; | |
69 | typedef mpl::list<unsigned long> unsigned_types; | |
70 | #endif | |
71 | typedef mpl::list<double, long double> float_types; | |
72 | typedef long exponent_type; | |
73 | ||
74 | mpc_complex_imp() | |
75 | { | |
f67539c2 | 76 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
77 | mpc_set_ui(m_data, 0u, GMP_RNDN); |
78 | } | |
79 | mpc_complex_imp(unsigned digits2) | |
80 | { | |
81 | mpc_init2(m_data, digits2); | |
82 | mpc_set_ui(m_data, 0u, GMP_RNDN); | |
83 | } | |
84 | ||
85 | mpc_complex_imp(const mpc_complex_imp& o) | |
86 | { | |
87 | mpc_init2(m_data, mpc_get_prec(o.m_data)); | |
88 | if (o.m_data[0].re[0]._mpfr_d) | |
89 | mpc_set(m_data, o.m_data, GMP_RNDN); | |
90 | } | |
91 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
92 | mpc_complex_imp(mpc_complex_imp&& o) BOOST_NOEXCEPT | |
93 | { | |
94 | m_data[0] = o.m_data[0]; | |
95 | o.m_data[0].re[0]._mpfr_d = 0; | |
96 | } | |
97 | #endif | |
98 | mpc_complex_imp& operator=(const mpc_complex_imp& o) | |
99 | { | |
100 | if ((o.m_data[0].re[0]._mpfr_d) && (this != &o)) | |
101 | { | |
102 | if (m_data[0].re[0]._mpfr_d == 0) | |
103 | mpc_init2(m_data, mpc_get_prec(o.m_data)); | |
104 | mpc_set(m_data, o.m_data, GMP_RNDD); | |
105 | } | |
106 | return *this; | |
107 | } | |
108 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
109 | mpc_complex_imp& operator=(mpc_complex_imp&& o) BOOST_NOEXCEPT | |
110 | { | |
111 | mpc_swap(m_data, o.m_data); | |
112 | return *this; | |
113 | } | |
114 | #endif | |
115 | #ifdef BOOST_HAS_LONG_LONG | |
116 | #ifdef _MPFR_H_HAVE_INTMAX_T | |
117 | mpc_complex_imp& operator=(boost::ulong_long_type i) | |
118 | { | |
119 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 120 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
121 | mpc_set_uj(data(), i, GMP_RNDD); |
122 | return *this; | |
123 | } | |
124 | mpc_complex_imp& operator=(boost::long_long_type i) | |
125 | { | |
126 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 127 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
128 | mpc_set_sj(data(), i, GMP_RNDD); |
129 | return *this; | |
130 | } | |
131 | #else | |
132 | mpc_complex_imp& operator=(boost::ulong_long_type i) | |
133 | { | |
134 | mpfr_float_backend<digits10> f(0uL, mpc_get_prec(m_data)); | |
135 | f = i; | |
136 | mpc_set_fr(this->data(), f.data(), GMP_RNDN); | |
137 | return *this; | |
138 | } | |
139 | mpc_complex_imp& operator=(boost::long_long_type i) | |
140 | { | |
141 | mpfr_float_backend<digits10> f(0uL, mpc_get_prec(m_data)); | |
142 | f = i; | |
143 | mpc_set_fr(this->data(), f.data(), GMP_RNDN); | |
144 | return *this; | |
145 | } | |
146 | #endif | |
147 | #endif | |
148 | mpc_complex_imp& operator=(unsigned long i) | |
149 | { | |
150 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 151 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
152 | mpc_set_ui(m_data, i, GMP_RNDN); |
153 | return *this; | |
154 | } | |
155 | mpc_complex_imp& operator=(long i) | |
156 | { | |
157 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 158 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
159 | mpc_set_si(m_data, i, GMP_RNDN); |
160 | return *this; | |
161 | } | |
162 | mpc_complex_imp& operator=(double d) | |
163 | { | |
164 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 165 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
166 | mpc_set_d(m_data, d, GMP_RNDN); |
167 | return *this; | |
168 | } | |
169 | mpc_complex_imp& operator=(long double d) | |
170 | { | |
171 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 172 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
173 | mpc_set_ld(m_data, d, GMP_RNDN); |
174 | return *this; | |
175 | } | |
176 | mpc_complex_imp& operator=(mpz_t i) | |
177 | { | |
178 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 179 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
180 | mpc_set_z(m_data, i, GMP_RNDN); |
181 | return *this; | |
182 | } | |
183 | mpc_complex_imp& operator=(gmp_int i) | |
184 | { | |
185 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 186 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
187 | mpc_set_z(m_data, i.data(), GMP_RNDN); |
188 | return *this; | |
189 | } | |
190 | ||
191 | mpc_complex_imp& operator=(const char* s) | |
192 | { | |
193 | using default_ops::eval_fpclassify; | |
194 | ||
195 | if (m_data[0].re[0]._mpfr_d == 0) | |
f67539c2 | 196 | mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
197 | |
198 | mpfr_float_backend<digits10> a(0uL, mpc_get_prec(m_data)), b(0uL, mpc_get_prec(m_data)); | |
199 | ||
200 | if (s && (*s == '(')) | |
201 | { | |
202 | std::string part; | |
203 | const char* p = ++s; | |
204 | while (*p && (*p != ',') && (*p != ')')) | |
205 | ++p; | |
206 | part.assign(s, p); | |
207 | if (part.size()) | |
208 | a = part.c_str(); | |
209 | else | |
210 | a = 0uL; | |
211 | s = p; | |
212 | if (*p && (*p != ')')) | |
213 | { | |
214 | ++p; | |
215 | while (*p && (*p != ')')) | |
216 | ++p; | |
217 | part.assign(s + 1, p); | |
218 | } | |
219 | else | |
220 | part.erase(); | |
221 | if (part.size()) | |
222 | b = part.c_str(); | |
223 | else | |
224 | b = 0uL; | |
225 | } | |
226 | else | |
227 | { | |
228 | a = s; | |
229 | b = 0uL; | |
230 | } | |
231 | ||
232 | if (eval_fpclassify(a) == (int)FP_NAN) | |
233 | { | |
234 | mpc_set_fr(this->data(), a.data(), GMP_RNDN); | |
235 | } | |
236 | else if (eval_fpclassify(b) == (int)FP_NAN) | |
237 | { | |
238 | mpc_set_fr(this->data(), b.data(), GMP_RNDN); | |
239 | } | |
240 | else | |
241 | { | |
242 | mpc_set_fr_fr(m_data, a.data(), b.data(), GMP_RNDN); | |
243 | } | |
244 | return *this; | |
245 | } | |
246 | void swap(mpc_complex_imp& o) BOOST_NOEXCEPT | |
247 | { | |
248 | mpc_swap(m_data, o.m_data); | |
249 | } | |
250 | std::string str(std::streamsize digits, std::ios_base::fmtflags f) const | |
251 | { | |
252 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d); | |
253 | ||
254 | mpfr_float_backend<digits10> a(0uL, mpc_get_prec(m_data)), b(0uL, mpc_get_prec(m_data)); | |
255 | ||
256 | mpc_real(a.data(), m_data, GMP_RNDD); | |
257 | mpc_imag(b.data(), m_data, GMP_RNDD); | |
258 | ||
259 | if (eval_is_zero(b)) | |
260 | return a.str(digits, f); | |
261 | ||
262 | return "(" + a.str(digits, f) + "," + b.str(digits, f) + ")"; | |
263 | } | |
264 | ~mpc_complex_imp() BOOST_NOEXCEPT | |
265 | { | |
266 | if (m_data[0].re[0]._mpfr_d) | |
267 | mpc_clear(m_data); | |
268 | } | |
269 | void negate() BOOST_NOEXCEPT | |
270 | { | |
271 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d); | |
272 | mpc_neg(m_data, m_data, GMP_RNDD); | |
273 | } | |
274 | int compare(const mpc_complex_imp& o) const BOOST_NOEXCEPT | |
275 | { | |
276 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d && o.m_data[0].re[0]._mpfr_d); | |
277 | return mpc_cmp(m_data, o.m_data); | |
278 | } | |
279 | int compare(const mpc_complex_backend<digits10>& o) const BOOST_NOEXCEPT | |
280 | { | |
281 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d && o.m_data[0].re[0]._mpfr_d); | |
282 | return mpc_cmp(m_data, o.data()); | |
283 | } | |
284 | int compare(long int i) const BOOST_NOEXCEPT | |
285 | { | |
286 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d); | |
287 | return mpc_cmp_si(m_data, i); | |
288 | } | |
289 | int compare(unsigned long int i) const BOOST_NOEXCEPT | |
290 | { | |
291 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d); | |
292 | static const unsigned long int max_val = (std::numeric_limits<long>::max)(); | |
293 | if (i > max_val) | |
294 | { | |
295 | mpc_complex_imp d(mpc_get_prec(m_data)); | |
296 | d = i; | |
297 | return compare(d); | |
298 | } | |
299 | return mpc_cmp_si(m_data, (long)i); | |
300 | } | |
301 | template <class V> | |
302 | int compare(const V& v) const BOOST_NOEXCEPT | |
303 | { | |
304 | mpc_complex_imp d(mpc_get_prec(m_data)); | |
305 | d = v; | |
306 | return compare(d); | |
307 | } | |
308 | mpc_t& data() BOOST_NOEXCEPT | |
309 | { | |
310 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d); | |
311 | return m_data; | |
312 | } | |
313 | const mpc_t& data() const BOOST_NOEXCEPT | |
314 | { | |
315 | BOOST_ASSERT(m_data[0].re[0]._mpfr_d); | |
316 | return m_data; | |
317 | } | |
318 | ||
319 | protected: | |
320 | mpc_t m_data; | |
f67539c2 | 321 | static boost::multiprecision::detail::precision_type& get_default_precision() BOOST_NOEXCEPT |
92f5a8d4 | 322 | { |
f67539c2 | 323 | static boost::multiprecision::detail::precision_type val(BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION); |
92f5a8d4 TL |
324 | return val; |
325 | } | |
326 | }; | |
327 | ||
328 | } // namespace detail | |
329 | ||
330 | template <unsigned digits10> | |
331 | struct mpc_complex_backend : public detail::mpc_complex_imp<digits10> | |
332 | { | |
333 | mpc_complex_backend() : detail::mpc_complex_imp<digits10>() {} | |
334 | mpc_complex_backend(const mpc_complex_backend& o) : detail::mpc_complex_imp<digits10>(o) {} | |
335 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
336 | mpc_complex_backend(mpc_complex_backend&& o) : detail::mpc_complex_imp<digits10>(static_cast<detail::mpc_complex_imp<digits10>&&>(o)) | |
337 | {} | |
338 | #endif | |
339 | template <unsigned D> | |
340 | mpc_complex_backend(const mpc_complex_backend<D>& val, typename enable_if_c<D <= digits10>::type* = 0) | |
341 | : detail::mpc_complex_imp<digits10>() | |
342 | { | |
343 | mpc_set(this->m_data, val.data(), GMP_RNDN); | |
344 | } | |
345 | template <unsigned D> | |
346 | explicit mpc_complex_backend(const mpc_complex_backend<D>& val, typename disable_if_c<D <= digits10>::type* = 0) | |
347 | : detail::mpc_complex_imp<digits10>() | |
348 | { | |
349 | mpc_set(this->m_data, val.data(), GMP_RNDN); | |
350 | } | |
351 | template <unsigned D> | |
352 | mpc_complex_backend(const mpfr_float_backend<D>& val, typename enable_if_c<D <= digits10>::type* = 0) | |
353 | : detail::mpc_complex_imp<digits10>() | |
354 | { | |
355 | mpc_set_fr(this->m_data, val.data(), GMP_RNDN); | |
356 | } | |
357 | template <unsigned D> | |
358 | explicit mpc_complex_backend(const mpfr_float_backend<D>& val, typename disable_if_c<D <= digits10>::type* = 0) | |
359 | : detail::mpc_complex_imp<digits10>() | |
360 | { | |
361 | mpc_set(this->m_data, val.data(), GMP_RNDN); | |
362 | } | |
363 | mpc_complex_backend(const mpc_t val) | |
364 | : detail::mpc_complex_imp<digits10>() | |
365 | { | |
366 | mpc_set(this->m_data, val, GMP_RNDN); | |
367 | } | |
368 | mpc_complex_backend(const std::complex<float>& val) | |
369 | : detail::mpc_complex_imp<digits10>() | |
370 | { | |
371 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
372 | } | |
373 | mpc_complex_backend(const std::complex<double>& val) | |
374 | : detail::mpc_complex_imp<digits10>() | |
375 | { | |
376 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
377 | } | |
378 | mpc_complex_backend(const std::complex<long double>& val) | |
379 | : detail::mpc_complex_imp<digits10>() | |
380 | { | |
381 | mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
382 | } | |
383 | mpc_complex_backend(mpz_srcptr val) : detail::mpc_complex_imp<digits10>() | |
384 | { | |
385 | mpc_set_z(this->m_data, val, GMP_RNDN); | |
386 | } | |
387 | mpc_complex_backend& operator=(mpz_srcptr val) | |
388 | { | |
389 | mpc_set_z(this->m_data, val, GMP_RNDN); | |
390 | return *this; | |
391 | } | |
392 | mpc_complex_backend(gmp_int const& val) : detail::mpc_complex_imp<digits10>() | |
393 | { | |
394 | mpc_set_z(this->m_data, val.data(), GMP_RNDN); | |
395 | } | |
396 | mpc_complex_backend& operator=(gmp_int const& val) | |
397 | { | |
398 | mpc_set_z(this->m_data, val.data(), GMP_RNDN); | |
399 | return *this; | |
400 | } | |
401 | mpc_complex_backend(mpf_srcptr val) : detail::mpc_complex_imp<digits10>() | |
402 | { | |
403 | mpc_set_f(this->m_data, val, GMP_RNDN); | |
404 | } | |
405 | mpc_complex_backend& operator=(mpf_srcptr val) | |
406 | { | |
407 | mpc_set_f(this->m_data, val, GMP_RNDN); | |
408 | return *this; | |
409 | } | |
410 | template <unsigned D10> | |
411 | mpc_complex_backend(gmp_float<D10> const& val) : detail::mpc_complex_imp<digits10>() | |
412 | { | |
413 | mpc_set_f(this->m_data, val.data(), GMP_RNDN); | |
414 | } | |
415 | template <unsigned D10> | |
416 | mpc_complex_backend& operator=(gmp_float<D10> const& val) | |
417 | { | |
418 | mpc_set_f(this->m_data, val.data(), GMP_RNDN); | |
419 | return *this; | |
420 | } | |
421 | mpc_complex_backend(mpq_srcptr val) : detail::mpc_complex_imp<digits10>() | |
422 | { | |
423 | mpc_set_q(this->m_data, val, GMP_RNDN); | |
424 | } | |
425 | mpc_complex_backend& operator=(mpq_srcptr val) | |
426 | { | |
427 | mpc_set_q(this->m_data, val, GMP_RNDN); | |
428 | return *this; | |
429 | } | |
430 | mpc_complex_backend(gmp_rational const& val) : detail::mpc_complex_imp<digits10>() | |
431 | { | |
432 | mpc_set_q(this->m_data, val.data(), GMP_RNDN); | |
433 | } | |
434 | mpc_complex_backend& operator=(gmp_rational const& val) | |
435 | { | |
436 | mpc_set_q(this->m_data, val.data(), GMP_RNDN); | |
437 | return *this; | |
438 | } | |
439 | mpc_complex_backend(mpfr_srcptr val) : detail::mpc_complex_imp<digits10>() | |
440 | { | |
441 | mpc_set_fr(this->m_data, val, GMP_RNDN); | |
442 | } | |
443 | mpc_complex_backend& operator=(mpfr_srcptr val) | |
444 | { | |
445 | mpc_set_fr(this->m_data, val, GMP_RNDN); | |
446 | return *this; | |
447 | } | |
448 | template <unsigned D10, mpfr_allocation_type AllocationType> | |
449 | mpc_complex_backend(mpfr_float_backend<D10, AllocationType> const& val) : detail::mpc_complex_imp<digits10>() | |
450 | { | |
451 | mpc_set_fr(this->m_data, val.data(), GMP_RNDN); | |
452 | } | |
453 | template <unsigned D10, mpfr_allocation_type AllocationType> | |
454 | mpc_complex_backend& operator=(mpfr_float_backend<D10, AllocationType> const& val) | |
455 | { | |
456 | mpc_set_fr(this->m_data, val.data(), GMP_RNDN); | |
457 | return *this; | |
458 | } | |
459 | mpc_complex_backend& operator=(const mpc_complex_backend& o) | |
460 | { | |
461 | *static_cast<detail::mpc_complex_imp<digits10>*>(this) = static_cast<detail::mpc_complex_imp<digits10> const&>(o); | |
462 | return *this; | |
463 | } | |
464 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
465 | mpc_complex_backend& operator=(mpc_complex_backend&& o) BOOST_NOEXCEPT | |
466 | { | |
467 | *static_cast<detail::mpc_complex_imp<digits10>*>(this) = static_cast<detail::mpc_complex_imp<digits10>&&>(o); | |
468 | return *this; | |
469 | } | |
470 | #endif | |
471 | template <class V> | |
472 | mpc_complex_backend& operator=(const V& v) | |
473 | { | |
474 | *static_cast<detail::mpc_complex_imp<digits10>*>(this) = v; | |
475 | return *this; | |
476 | } | |
477 | mpc_complex_backend& operator=(const mpc_t val) | |
478 | { | |
479 | mpc_set(this->m_data, val, GMP_RNDN); | |
480 | return *this; | |
481 | } | |
482 | mpc_complex_backend& operator=(const std::complex<float>& val) | |
483 | { | |
484 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
485 | return *this; | |
486 | } | |
487 | mpc_complex_backend& operator=(const std::complex<double>& val) | |
488 | { | |
489 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
490 | return *this; | |
491 | } | |
492 | mpc_complex_backend& operator=(const std::complex<long double>& val) | |
493 | { | |
494 | mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
495 | return *this; | |
496 | } | |
497 | // We don't change our precision here, this is a fixed precision type: | |
498 | template <unsigned D> | |
499 | mpc_complex_backend& operator=(const mpc_complex_backend<D>& val) | |
500 | { | |
501 | mpc_set(this->m_data, val.data(), GMP_RNDN); | |
502 | return *this; | |
503 | } | |
504 | }; | |
505 | ||
506 | template <> | |
507 | struct mpc_complex_backend<0> : public detail::mpc_complex_imp<0> | |
508 | { | |
509 | mpc_complex_backend() : detail::mpc_complex_imp<0>() {} | |
510 | mpc_complex_backend(const mpc_t val) | |
511 | : detail::mpc_complex_imp<0>(mpc_get_prec(val)) | |
512 | { | |
513 | mpc_set(this->m_data, val, GMP_RNDN); | |
514 | } | |
515 | mpc_complex_backend(const mpc_complex_backend& o) : detail::mpc_complex_imp<0>(o) {} | |
516 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
517 | mpc_complex_backend(mpc_complex_backend&& o) BOOST_NOEXCEPT : detail::mpc_complex_imp<0>(static_cast<detail::mpc_complex_imp<0>&&>(o)) | |
518 | {} | |
519 | #endif | |
520 | mpc_complex_backend(const mpc_complex_backend& o, unsigned digits10) | |
521 | : detail::mpc_complex_imp<0>(multiprecision::detail::digits10_2_2(digits10)) | |
522 | { | |
523 | mpc_set(this->m_data, o.data(), GMP_RNDN); | |
524 | } | |
525 | template <unsigned D> | |
526 | mpc_complex_backend(const mpc_complex_backend<D>& val) | |
527 | : detail::mpc_complex_imp<0>(mpc_get_prec(val.data())) | |
528 | { | |
529 | mpc_set(this->m_data, val.data(), GMP_RNDN); | |
530 | } | |
531 | template <unsigned D> | |
532 | mpc_complex_backend(const mpfr_float_backend<D>& val) | |
533 | : detail::mpc_complex_imp<0>(mpfr_get_prec(val.data())) | |
534 | { | |
535 | mpc_set_fr(this->m_data, val.data(), GMP_RNDN); | |
536 | } | |
537 | mpc_complex_backend(mpz_srcptr val) : detail::mpc_complex_imp<0>() | |
538 | { | |
539 | mpc_set_z(this->m_data, val, GMP_RNDN); | |
540 | } | |
541 | mpc_complex_backend& operator=(mpz_srcptr val) | |
542 | { | |
543 | mpc_set_z(this->m_data, val, GMP_RNDN); | |
544 | return *this; | |
545 | } | |
546 | mpc_complex_backend(gmp_int const& val) : detail::mpc_complex_imp<0>() | |
547 | { | |
548 | mpc_set_z(this->m_data, val.data(), GMP_RNDN); | |
549 | } | |
550 | mpc_complex_backend& operator=(gmp_int const& val) | |
551 | { | |
552 | mpc_set_z(this->m_data, val.data(), GMP_RNDN); | |
553 | return *this; | |
554 | } | |
555 | mpc_complex_backend(mpf_srcptr val) : detail::mpc_complex_imp<0>((unsigned)mpf_get_prec(val)) | |
556 | { | |
557 | mpc_set_f(this->m_data, val, GMP_RNDN); | |
558 | } | |
559 | mpc_complex_backend& operator=(mpf_srcptr val) | |
560 | { | |
561 | if ((mp_bitcnt_t)mpc_get_prec(data()) != mpf_get_prec(val)) | |
562 | { | |
563 | mpc_complex_backend t(val); | |
564 | t.swap(*this); | |
565 | } | |
566 | else | |
567 | mpc_set_f(this->m_data, val, GMP_RNDN); | |
568 | return *this; | |
569 | } | |
570 | template <unsigned digits10> | |
571 | mpc_complex_backend(gmp_float<digits10> const& val) : detail::mpc_complex_imp<0>((unsigned)mpf_get_prec(val.data())) | |
572 | { | |
573 | mpc_set_f(this->m_data, val.data(), GMP_RNDN); | |
574 | } | |
575 | template <unsigned digits10> | |
576 | mpc_complex_backend& operator=(gmp_float<digits10> const& val) | |
577 | { | |
578 | if (mpc_get_prec(data()) != (mpfr_prec_t)mpf_get_prec(val.data())) | |
579 | { | |
580 | mpc_complex_backend t(val); | |
581 | t.swap(*this); | |
582 | } | |
583 | else | |
584 | mpc_set_f(this->m_data, val.data(), GMP_RNDN); | |
585 | return *this; | |
586 | } | |
587 | mpc_complex_backend(mpq_srcptr val) : detail::mpc_complex_imp<0>() | |
588 | { | |
589 | mpc_set_q(this->m_data, val, GMP_RNDN); | |
590 | } | |
591 | mpc_complex_backend& operator=(mpq_srcptr val) | |
592 | { | |
593 | mpc_set_q(this->m_data, val, GMP_RNDN); | |
594 | return *this; | |
595 | } | |
596 | mpc_complex_backend(gmp_rational const& val) : detail::mpc_complex_imp<0>() | |
597 | { | |
598 | mpc_set_q(this->m_data, val.data(), GMP_RNDN); | |
599 | } | |
600 | mpc_complex_backend& operator=(gmp_rational const& val) | |
601 | { | |
602 | mpc_set_q(this->m_data, val.data(), GMP_RNDN); | |
603 | return *this; | |
604 | } | |
605 | mpc_complex_backend(mpfr_srcptr val) : detail::mpc_complex_imp<0>(mpfr_get_prec(val)) | |
606 | { | |
607 | mpc_set_fr(this->m_data, val, GMP_RNDN); | |
608 | } | |
609 | mpc_complex_backend& operator=(mpfr_srcptr val) | |
610 | { | |
611 | if (mpc_get_prec(data()) != mpfr_get_prec(val)) | |
612 | { | |
613 | mpc_complex_backend t(val); | |
614 | t.swap(*this); | |
615 | } | |
616 | else | |
617 | mpc_set_fr(this->m_data, val, GMP_RNDN); | |
618 | return *this; | |
619 | } | |
620 | mpc_complex_backend(const std::complex<float>& val) | |
621 | : detail::mpc_complex_imp<0>() | |
622 | { | |
623 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
624 | } | |
625 | mpc_complex_backend(const std::complex<double>& val) | |
626 | : detail::mpc_complex_imp<0>() | |
627 | { | |
628 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
629 | } | |
630 | mpc_complex_backend(const std::complex<long double>& val) | |
631 | : detail::mpc_complex_imp<0>() | |
632 | { | |
633 | mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
634 | } | |
635 | // Construction with precision: | |
636 | template <class T, class U> | |
637 | mpc_complex_backend(const T& a, const U& b, unsigned digits10) | |
638 | : detail::mpc_complex_imp<0>(multiprecision::detail::digits10_2_2(digits10)) | |
639 | { | |
640 | // We can't use assign_components here because it copies the precision of | |
641 | // a and b, not digits10.... | |
642 | mpfr_float ca(a), cb(b); | |
643 | mpc_set_fr_fr(this->data(), ca.backend().data(), cb.backend().data(), GMP_RNDN); | |
644 | } | |
645 | template <unsigned N> | |
646 | mpc_complex_backend(const mpfr_float_backend<N>& a, const mpfr_float_backend<N>& b, unsigned digits10) | |
647 | : detail::mpc_complex_imp<0>(multiprecision::detail::digits10_2_2(digits10)) | |
648 | { | |
649 | mpc_set_fr_fr(this->data(), a.data(), b.data(), GMP_RNDN); | |
650 | } | |
651 | ||
652 | mpc_complex_backend& operator=(const mpc_complex_backend& o) | |
653 | { | |
654 | if (this != &o) | |
655 | { | |
656 | detail::mpc_copy_precision(this->m_data, o.data()); | |
657 | mpc_set(this->m_data, o.data(), GMP_RNDN); | |
658 | } | |
659 | return *this; | |
660 | } | |
661 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
662 | mpc_complex_backend& operator=(mpc_complex_backend&& o) BOOST_NOEXCEPT | |
663 | { | |
664 | *static_cast<detail::mpc_complex_imp<0>*>(this) = static_cast<detail::mpc_complex_imp<0>&&>(o); | |
665 | return *this; | |
666 | } | |
667 | #endif | |
668 | template <class V> | |
669 | mpc_complex_backend& operator=(const V& v) | |
670 | { | |
671 | *static_cast<detail::mpc_complex_imp<0>*>(this) = v; | |
672 | return *this; | |
673 | } | |
674 | mpc_complex_backend& operator=(const mpc_t val) | |
675 | { | |
676 | mpc_set_prec(this->m_data, mpc_get_prec(val)); | |
677 | mpc_set(this->m_data, val, GMP_RNDN); | |
678 | return *this; | |
679 | } | |
680 | template <unsigned D> | |
681 | mpc_complex_backend& operator=(const mpc_complex_backend<D>& val) | |
682 | { | |
683 | mpc_set_prec(this->m_data, mpc_get_prec(val.data())); | |
684 | mpc_set(this->m_data, val.data(), GMP_RNDN); | |
685 | return *this; | |
686 | } | |
687 | template <unsigned D> | |
688 | mpc_complex_backend& operator=(const mpfr_float_backend<D>& val) | |
689 | { | |
690 | mpc_set_prec(this->m_data, mpfr_get_prec(val.data())); | |
691 | mpc_set_fr(this->m_data, val.data(), GMP_RNDN); | |
692 | return *this; | |
693 | } | |
694 | mpc_complex_backend& operator=(const std::complex<float>& val) | |
695 | { | |
696 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
697 | return *this; | |
698 | } | |
699 | mpc_complex_backend& operator=(const std::complex<double>& val) | |
700 | { | |
701 | mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
702 | return *this; | |
703 | } | |
704 | mpc_complex_backend& operator=(const std::complex<long double>& val) | |
705 | { | |
706 | mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN); | |
707 | return *this; | |
708 | } | |
709 | static unsigned default_precision() BOOST_NOEXCEPT | |
710 | { | |
711 | return get_default_precision(); | |
712 | } | |
713 | static void default_precision(unsigned v) BOOST_NOEXCEPT | |
714 | { | |
715 | get_default_precision() = v; | |
716 | } | |
717 | unsigned precision() const BOOST_NOEXCEPT | |
718 | { | |
719 | return multiprecision::detail::digits2_2_10(mpc_get_prec(this->m_data)); | |
720 | } | |
721 | void precision(unsigned digits10) BOOST_NOEXCEPT | |
722 | { | |
723 | mpfr_prec_round(mpc_realref(this->m_data), multiprecision::detail::digits10_2_2((digits10)), GMP_RNDN); | |
724 | mpfr_prec_round(mpc_imagref(this->m_data), multiprecision::detail::digits10_2_2((digits10)), GMP_RNDN); | |
725 | } | |
726 | }; | |
727 | ||
728 | template <unsigned digits10, class T> | |
729 | inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const mpc_complex_backend<digits10>& a, const T& b) BOOST_NOEXCEPT | |
730 | { | |
731 | return a.compare(b) == 0; | |
732 | } | |
733 | template <unsigned digits10, class T> | |
734 | inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const mpc_complex_backend<digits10>& a, const T& b) BOOST_NOEXCEPT | |
735 | { | |
736 | return a.compare(b) < 0; | |
737 | } | |
738 | template <unsigned digits10, class T> | |
739 | inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const mpc_complex_backend<digits10>& a, const T& b) BOOST_NOEXCEPT | |
740 | { | |
741 | return a.compare(b) > 0; | |
742 | } | |
743 | ||
744 | template <unsigned D1, unsigned D2> | |
745 | inline void eval_add(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o) | |
746 | { | |
747 | mpc_add(result.data(), result.data(), o.data(), GMP_RNDD); | |
748 | } | |
749 | template <unsigned D1, unsigned D2> | |
750 | inline void eval_add(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o) | |
751 | { | |
752 | mpc_add_fr(result.data(), result.data(), o.data(), GMP_RNDD); | |
753 | } | |
754 | template <unsigned D1, unsigned D2> | |
755 | inline void eval_subtract(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o) | |
756 | { | |
757 | mpc_sub(result.data(), result.data(), o.data(), GMP_RNDD); | |
758 | } | |
759 | template <unsigned D1, unsigned D2> | |
760 | inline void eval_subtract(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o) | |
761 | { | |
762 | mpc_sub_fr(result.data(), result.data(), o.data(), GMP_RNDD); | |
763 | } | |
764 | template <unsigned D1, unsigned D2> | |
765 | inline void eval_multiply(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o) | |
766 | { | |
767 | if ((void*)&result == (void*)&o) | |
768 | mpc_sqr(result.data(), o.data(), GMP_RNDN); | |
769 | else | |
770 | mpc_mul(result.data(), result.data(), o.data(), GMP_RNDN); | |
771 | } | |
772 | template <unsigned D1, unsigned D2> | |
773 | inline void eval_multiply(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o) | |
774 | { | |
775 | mpc_mul_fr(result.data(), result.data(), o.data(), GMP_RNDN); | |
776 | } | |
777 | template <unsigned D1, unsigned D2> | |
778 | inline void eval_divide(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o) | |
779 | { | |
780 | mpc_div(result.data(), result.data(), o.data(), GMP_RNDD); | |
781 | } | |
782 | template <unsigned D1, unsigned D2> | |
783 | inline void eval_divide(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o) | |
784 | { | |
785 | mpc_div_fr(result.data(), result.data(), o.data(), GMP_RNDD); | |
786 | } | |
787 | template <unsigned digits10> | |
788 | inline void eval_add(mpc_complex_backend<digits10>& result, unsigned long i) | |
789 | { | |
790 | mpc_add_ui(result.data(), result.data(), i, GMP_RNDN); | |
791 | } | |
792 | template <unsigned digits10> | |
793 | inline void eval_subtract(mpc_complex_backend<digits10>& result, unsigned long i) | |
794 | { | |
795 | mpc_sub_ui(result.data(), result.data(), i, GMP_RNDN); | |
796 | } | |
797 | template <unsigned digits10> | |
798 | inline void eval_multiply(mpc_complex_backend<digits10>& result, unsigned long i) | |
799 | { | |
800 | mpc_mul_ui(result.data(), result.data(), i, GMP_RNDN); | |
801 | } | |
802 | template <unsigned digits10> | |
803 | inline void eval_divide(mpc_complex_backend<digits10>& result, unsigned long i) | |
804 | { | |
805 | mpc_div_ui(result.data(), result.data(), i, GMP_RNDN); | |
806 | } | |
807 | template <unsigned digits10> | |
808 | inline void eval_add(mpc_complex_backend<digits10>& result, long i) | |
809 | { | |
810 | if (i > 0) | |
811 | mpc_add_ui(result.data(), result.data(), i, GMP_RNDN); | |
812 | else | |
813 | mpc_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN); | |
814 | } | |
815 | template <unsigned digits10> | |
816 | inline void eval_subtract(mpc_complex_backend<digits10>& result, long i) | |
817 | { | |
818 | if (i > 0) | |
819 | mpc_sub_ui(result.data(), result.data(), i, GMP_RNDN); | |
820 | else | |
821 | mpc_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN); | |
822 | } | |
823 | template <unsigned digits10> | |
824 | inline void eval_multiply(mpc_complex_backend<digits10>& result, long i) | |
825 | { | |
826 | mpc_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN); | |
827 | if (i < 0) | |
828 | mpc_neg(result.data(), result.data(), GMP_RNDN); | |
829 | } | |
830 | template <unsigned digits10> | |
831 | inline void eval_divide(mpc_complex_backend<digits10>& result, long i) | |
832 | { | |
833 | mpc_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN); | |
834 | if (i < 0) | |
835 | mpc_neg(result.data(), result.data(), GMP_RNDN); | |
836 | } | |
837 | // | |
838 | // Specialised 3 arg versions of the basic operators: | |
839 | // | |
840 | template <unsigned D1, unsigned D2, unsigned D3> | |
841 | inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
842 | { | |
843 | mpc_add(a.data(), x.data(), y.data(), GMP_RNDD); | |
844 | } | |
845 | template <unsigned D1, unsigned D2, unsigned D3> | |
846 | inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y) | |
847 | { | |
848 | mpc_add_fr(a.data(), x.data(), y.data(), GMP_RNDD); | |
849 | } | |
850 | template <unsigned D1, unsigned D2, unsigned D3> | |
851 | inline void eval_add(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
852 | { | |
853 | mpc_add_fr(a.data(), y.data(), x.data(), GMP_RNDD); | |
854 | } | |
855 | template <unsigned D1, unsigned D2> | |
856 | inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y) | |
857 | { | |
858 | mpc_add_ui(a.data(), x.data(), y, GMP_RNDD); | |
859 | } | |
860 | template <unsigned D1, unsigned D2> | |
861 | inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y) | |
862 | { | |
863 | if (y < 0) | |
864 | mpc_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDD); | |
865 | else | |
866 | mpc_add_ui(a.data(), x.data(), y, GMP_RNDD); | |
867 | } | |
868 | template <unsigned D1, unsigned D2> | |
869 | inline void eval_add(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y) | |
870 | { | |
871 | mpc_add_ui(a.data(), y.data(), x, GMP_RNDD); | |
872 | } | |
873 | template <unsigned D1, unsigned D2> | |
874 | inline void eval_add(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y) | |
875 | { | |
876 | if (x < 0) | |
877 | { | |
878 | mpc_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN); | |
879 | mpc_neg(a.data(), a.data(), GMP_RNDD); | |
880 | } | |
881 | else | |
882 | mpc_add_ui(a.data(), y.data(), x, GMP_RNDD); | |
883 | } | |
884 | template <unsigned D1, unsigned D2, unsigned D3> | |
885 | inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
886 | { | |
887 | mpc_sub(a.data(), x.data(), y.data(), GMP_RNDD); | |
888 | } | |
889 | template <unsigned D1, unsigned D2, unsigned D3> | |
890 | inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y) | |
891 | { | |
892 | mpc_sub_fr(a.data(), x.data(), y.data(), GMP_RNDD); | |
893 | } | |
894 | template <unsigned D1, unsigned D2, unsigned D3> | |
895 | inline void eval_subtract(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
896 | { | |
897 | mpc_fr_sub(a.data(), x.data(), y.data(), GMP_RNDD); | |
898 | } | |
899 | template <unsigned D1, unsigned D2> | |
900 | inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y) | |
901 | { | |
902 | mpc_sub_ui(a.data(), x.data(), y, GMP_RNDD); | |
903 | } | |
904 | template <unsigned D1, unsigned D2> | |
905 | inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y) | |
906 | { | |
907 | if (y < 0) | |
908 | mpc_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDD); | |
909 | else | |
910 | mpc_sub_ui(a.data(), x.data(), y, GMP_RNDD); | |
911 | } | |
912 | template <unsigned D1, unsigned D2> | |
913 | inline void eval_subtract(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y) | |
914 | { | |
915 | mpc_ui_sub(a.data(), x, y.data(), GMP_RNDN); | |
916 | } | |
917 | template <unsigned D1, unsigned D2> | |
918 | inline void eval_subtract(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y) | |
919 | { | |
920 | if (x < 0) | |
921 | { | |
922 | mpc_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDD); | |
923 | mpc_neg(a.data(), a.data(), GMP_RNDD); | |
924 | } | |
925 | else | |
926 | mpc_ui_sub(a.data(), x, y.data(), GMP_RNDN); | |
927 | } | |
928 | ||
929 | template <unsigned D1, unsigned D2, unsigned D3> | |
930 | inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
931 | { | |
932 | if ((void*)&x == (void*)&y) | |
933 | mpc_sqr(a.data(), x.data(), GMP_RNDD); | |
934 | else | |
935 | mpc_mul(a.data(), x.data(), y.data(), GMP_RNDD); | |
936 | } | |
937 | template <unsigned D1, unsigned D2, unsigned D3> | |
938 | inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y) | |
939 | { | |
940 | mpc_mul_fr(a.data(), x.data(), y.data(), GMP_RNDD); | |
941 | } | |
942 | template <unsigned D1, unsigned D2, unsigned D3> | |
943 | inline void eval_multiply(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
944 | { | |
945 | mpc_mul_fr(a.data(), y.data(), x.data(), GMP_RNDD); | |
946 | } | |
947 | template <unsigned D1, unsigned D2> | |
948 | inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y) | |
949 | { | |
950 | mpc_mul_ui(a.data(), x.data(), y, GMP_RNDD); | |
951 | } | |
952 | template <unsigned D1, unsigned D2> | |
953 | inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y) | |
954 | { | |
955 | if (y < 0) | |
956 | { | |
957 | mpc_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDD); | |
958 | a.negate(); | |
959 | } | |
960 | else | |
961 | mpc_mul_ui(a.data(), x.data(), y, GMP_RNDD); | |
962 | } | |
963 | template <unsigned D1, unsigned D2> | |
964 | inline void eval_multiply(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y) | |
965 | { | |
966 | mpc_mul_ui(a.data(), y.data(), x, GMP_RNDD); | |
967 | } | |
968 | template <unsigned D1, unsigned D2> | |
969 | inline void eval_multiply(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y) | |
970 | { | |
971 | if (x < 0) | |
972 | { | |
973 | mpc_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDD); | |
974 | mpc_neg(a.data(), a.data(), GMP_RNDD); | |
975 | } | |
976 | else | |
977 | mpc_mul_ui(a.data(), y.data(), x, GMP_RNDD); | |
978 | } | |
979 | ||
980 | template <unsigned D1, unsigned D2, unsigned D3> | |
981 | inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
982 | { | |
983 | mpc_div(a.data(), x.data(), y.data(), GMP_RNDD); | |
984 | } | |
985 | template <unsigned D1, unsigned D2, unsigned D3> | |
986 | inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y) | |
987 | { | |
988 | mpc_div_fr(a.data(), x.data(), y.data(), GMP_RNDD); | |
989 | } | |
990 | template <unsigned D1, unsigned D2, unsigned D3> | |
991 | inline void eval_divide(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y) | |
992 | { | |
993 | mpc_fr_div(a.data(), x.data(), y.data(), GMP_RNDD); | |
994 | } | |
995 | template <unsigned D1, unsigned D2> | |
996 | inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y) | |
997 | { | |
998 | mpc_div_ui(a.data(), x.data(), y, GMP_RNDD); | |
999 | } | |
1000 | template <unsigned D1, unsigned D2> | |
1001 | inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y) | |
1002 | { | |
1003 | if (y < 0) | |
1004 | { | |
1005 | mpc_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDD); | |
1006 | a.negate(); | |
1007 | } | |
1008 | else | |
1009 | mpc_div_ui(a.data(), x.data(), y, GMP_RNDD); | |
1010 | } | |
1011 | template <unsigned D1, unsigned D2> | |
1012 | inline void eval_divide(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y) | |
1013 | { | |
1014 | mpc_ui_div(a.data(), x, y.data(), GMP_RNDD); | |
1015 | } | |
1016 | template <unsigned D1, unsigned D2> | |
1017 | inline void eval_divide(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y) | |
1018 | { | |
1019 | if (x < 0) | |
1020 | { | |
1021 | mpc_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDD); | |
1022 | mpc_neg(a.data(), a.data(), GMP_RNDD); | |
1023 | } | |
1024 | else | |
1025 | mpc_ui_div(a.data(), x, y.data(), GMP_RNDD); | |
1026 | } | |
1027 | ||
1028 | template <unsigned digits10> | |
1029 | inline bool eval_is_zero(const mpc_complex_backend<digits10>& val) BOOST_NOEXCEPT | |
1030 | { | |
1031 | return (0 != mpfr_zero_p(mpc_realref(val.data()))) && (0 != mpfr_zero_p(mpc_imagref(val.data()))); | |
1032 | } | |
1033 | template <unsigned digits10> | |
1034 | inline int eval_get_sign(const mpc_complex_backend<digits10>&) | |
1035 | { | |
1036 | BOOST_STATIC_ASSERT_MSG(digits10 == UINT_MAX, "Complex numbers have no sign bit."); // designed to always fail | |
1037 | return 0; | |
1038 | } | |
1039 | ||
1040 | template <unsigned digits10> | |
1041 | inline void eval_convert_to(unsigned long* result, const mpc_complex_backend<digits10>& val) | |
1042 | { | |
1043 | if (0 == mpfr_zero_p(mpc_imagref(val.data()))) | |
1044 | { | |
1045 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); | |
1046 | } | |
1047 | mpfr_float_backend<digits10> t; | |
1048 | mpc_real(t.data(), val.data(), GMP_RNDN); | |
1049 | eval_convert_to(result, t); | |
1050 | } | |
1051 | template <unsigned digits10> | |
1052 | inline void eval_convert_to(long* result, const mpc_complex_backend<digits10>& val) | |
1053 | { | |
1054 | if (0 == mpfr_zero_p(mpc_imagref(val.data()))) | |
1055 | { | |
1056 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); | |
1057 | } | |
1058 | mpfr_float_backend<digits10> t; | |
1059 | mpc_real(t.data(), val.data(), GMP_RNDN); | |
1060 | eval_convert_to(result, t); | |
1061 | } | |
1062 | #ifdef _MPFR_H_HAVE_INTMAX_T | |
1063 | template <unsigned digits10> | |
1064 | inline void eval_convert_to(boost::ulong_long_type* result, const mpc_complex_backend<digits10>& val) | |
1065 | { | |
1066 | if (0 == mpfr_zero_p(mpc_imagref(val.data()))) | |
1067 | { | |
1068 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); | |
1069 | } | |
1070 | mpfr_float_backend<digits10> t; | |
1071 | mpc_real(t.data(), val.data(), GMP_RNDN); | |
1072 | eval_convert_to(result, t); | |
1073 | } | |
1074 | template <unsigned digits10> | |
1075 | inline void eval_convert_to(boost::long_long_type* result, const mpc_complex_backend<digits10>& val) | |
1076 | { | |
1077 | if (0 == mpfr_zero_p(mpc_imagref(val.data()))) | |
1078 | { | |
1079 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); | |
1080 | } | |
1081 | mpfr_float_backend<digits10> t; | |
1082 | mpc_real(t.data(), val.data(), GMP_RNDN); | |
1083 | eval_convert_to(result, t); | |
1084 | } | |
1085 | #endif | |
1086 | template <unsigned digits10> | |
1087 | inline void eval_convert_to(double* result, const mpc_complex_backend<digits10>& val) BOOST_NOEXCEPT | |
1088 | { | |
1089 | if (0 == mpfr_zero_p(mpc_imagref(val.data()))) | |
1090 | { | |
1091 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); | |
1092 | } | |
1093 | mpfr_float_backend<digits10> t; | |
1094 | mpc_real(t.data(), val.data(), GMP_RNDN); | |
1095 | eval_convert_to(result, t); | |
1096 | } | |
1097 | template <unsigned digits10> | |
1098 | inline void eval_convert_to(long double* result, const mpc_complex_backend<digits10>& val) BOOST_NOEXCEPT | |
1099 | { | |
1100 | if (0 == mpfr_zero_p(mpc_imagref(val.data()))) | |
1101 | { | |
1102 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar.")); | |
1103 | } | |
1104 | mpfr_float_backend<digits10> t; | |
1105 | mpc_real(t.data(), val.data(), GMP_RNDN); | |
1106 | eval_convert_to(result, t); | |
1107 | } | |
1108 | ||
1109 | template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType> | |
1110 | inline void assign_components(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b) | |
1111 | { | |
1112 | // | |
1113 | // This is called from class number's constructors, so if we have variable | |
1114 | // precision, then copy the precision of the source variables. | |
1115 | // | |
1116 | if (!D1) | |
1117 | { | |
1118 | unsigned long prec = (std::max)(mpfr_get_prec(a.data()), mpfr_get_prec(b.data())); | |
1119 | mpc_set_prec(result.data(), prec); | |
1120 | } | |
1121 | using default_ops::eval_fpclassify; | |
1122 | if (eval_fpclassify(a) == (int)FP_NAN) | |
1123 | { | |
1124 | mpc_set_fr(result.data(), a.data(), GMP_RNDN); | |
1125 | } | |
1126 | else if (eval_fpclassify(b) == (int)FP_NAN) | |
1127 | { | |
1128 | mpc_set_fr(result.data(), b.data(), GMP_RNDN); | |
1129 | } | |
1130 | else | |
1131 | { | |
1132 | mpc_set_fr_fr(result.data(), a.data(), b.data(), GMP_RNDN); | |
1133 | } | |
1134 | } | |
1135 | ||
1136 | template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType> | |
1137 | inline void assign_components(mpc_complex_backend<D1>& result, unsigned long a, unsigned long b) | |
1138 | { | |
1139 | mpc_set_ui_ui(result.data(), a, b, GMP_RNDN); | |
1140 | } | |
1141 | ||
1142 | template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType> | |
1143 | inline void assign_components(mpc_complex_backend<D1>& result, long a, long b) | |
1144 | { | |
1145 | mpc_set_si_si(result.data(), a, b, GMP_RNDN); | |
1146 | } | |
1147 | ||
1148 | #if defined(BOOST_HAS_LONG_LONG) && defined(_MPFR_H_HAVE_INTMAX_T) | |
1149 | template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType> | |
1150 | inline void assign_components(mpc_complex_backend<D1>& result, unsigned long long a, unsigned long long b) | |
1151 | { | |
1152 | mpc_set_uj_uj(result.data(), a, b, GMP_RNDN); | |
1153 | } | |
1154 | ||
1155 | template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType> | |
1156 | inline void assign_components(mpc_complex_backend<D1>& result, long long a, long long b) | |
1157 | { | |
1158 | mpc_set_sj_sj(result.data(), a, b, GMP_RNDN); | |
1159 | } | |
1160 | #endif | |
1161 | ||
1162 | template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType> | |
1163 | inline void assign_components(mpc_complex_backend<D1>& result, double a, double b) | |
1164 | { | |
1165 | if ((boost::math::isnan)(a)) | |
1166 | { | |
1167 | mpc_set_d(result.data(), a, GMP_RNDN); | |
1168 | } | |
1169 | else if ((boost::math::isnan)(b)) | |
1170 | { | |
1171 | mpc_set_d(result.data(), b, GMP_RNDN); | |
1172 | } | |
1173 | else | |
1174 | { | |
1175 | mpc_set_d_d(result.data(), a, b, GMP_RNDN); | |
1176 | } | |
1177 | } | |
1178 | ||
1179 | template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType> | |
1180 | inline void assign_components(mpc_complex_backend<D1>& result, long double a, long double b) | |
1181 | { | |
1182 | if ((boost::math::isnan)(a)) | |
1183 | { | |
1184 | mpc_set_d(result.data(), a, GMP_RNDN); | |
1185 | } | |
1186 | else if ((boost::math::isnan)(b)) | |
1187 | { | |
1188 | mpc_set_d(result.data(), b, GMP_RNDN); | |
1189 | } | |
1190 | else | |
1191 | { | |
1192 | mpc_set_ld_ld(result.data(), a, b, GMP_RNDN); | |
1193 | } | |
1194 | } | |
1195 | ||
1196 | // | |
1197 | // Native non-member operations: | |
1198 | // | |
1199 | template <unsigned Digits10> | |
1200 | inline void eval_sqrt(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& val) | |
1201 | { | |
1202 | mpc_sqrt(result.data(), val.data(), GMP_RNDN); | |
1203 | } | |
1204 | ||
1205 | template <unsigned Digits10> | |
1206 | inline void eval_pow(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& b, const mpc_complex_backend<Digits10>& e) | |
1207 | { | |
1208 | mpc_pow(result.data(), b.data(), e.data(), GMP_RNDN); | |
1209 | } | |
1210 | ||
1211 | template <unsigned Digits10> | |
1212 | inline void eval_exp(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1213 | { | |
1214 | mpc_exp(result.data(), arg.data(), GMP_RNDN); | |
1215 | } | |
1216 | ||
1217 | template <unsigned Digits10> | |
1218 | inline void eval_log(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1219 | { | |
1220 | mpc_log(result.data(), arg.data(), GMP_RNDN); | |
1221 | } | |
1222 | ||
1223 | template <unsigned Digits10> | |
1224 | inline void eval_log10(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1225 | { | |
1226 | mpc_log10(result.data(), arg.data(), GMP_RNDN); | |
1227 | } | |
1228 | ||
1229 | template <unsigned Digits10> | |
1230 | inline void eval_sin(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1231 | { | |
1232 | mpc_sin(result.data(), arg.data(), GMP_RNDN); | |
1233 | } | |
1234 | ||
1235 | template <unsigned Digits10> | |
1236 | inline void eval_cos(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1237 | { | |
1238 | mpc_cos(result.data(), arg.data(), GMP_RNDN); | |
1239 | } | |
1240 | ||
1241 | template <unsigned Digits10> | |
1242 | inline void eval_tan(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1243 | { | |
1244 | mpc_tan(result.data(), arg.data(), GMP_RNDN); | |
1245 | } | |
1246 | ||
1247 | template <unsigned Digits10> | |
1248 | inline void eval_asin(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1249 | { | |
1250 | mpc_asin(result.data(), arg.data(), GMP_RNDN); | |
1251 | } | |
1252 | ||
1253 | template <unsigned Digits10> | |
1254 | inline void eval_acos(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1255 | { | |
1256 | mpc_acos(result.data(), arg.data(), GMP_RNDN); | |
1257 | } | |
1258 | ||
1259 | template <unsigned Digits10> | |
1260 | inline void eval_atan(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1261 | { | |
1262 | mpc_atan(result.data(), arg.data(), GMP_RNDN); | |
1263 | } | |
1264 | ||
1265 | template <unsigned Digits10> | |
1266 | inline void eval_sinh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1267 | { | |
1268 | mpc_sinh(result.data(), arg.data(), GMP_RNDN); | |
1269 | } | |
1270 | ||
1271 | template <unsigned Digits10> | |
1272 | inline void eval_cosh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1273 | { | |
1274 | mpc_cosh(result.data(), arg.data(), GMP_RNDN); | |
1275 | } | |
1276 | ||
1277 | template <unsigned Digits10> | |
1278 | inline void eval_tanh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1279 | { | |
1280 | mpc_tanh(result.data(), arg.data(), GMP_RNDN); | |
1281 | } | |
1282 | ||
1283 | template <unsigned Digits10> | |
1284 | inline void eval_asinh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1285 | { | |
1286 | mpc_asinh(result.data(), arg.data(), GMP_RNDN); | |
1287 | } | |
1288 | ||
1289 | template <unsigned Digits10> | |
1290 | inline void eval_acosh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1291 | { | |
1292 | mpc_acosh(result.data(), arg.data(), GMP_RNDN); | |
1293 | } | |
1294 | ||
1295 | template <unsigned Digits10> | |
1296 | inline void eval_atanh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1297 | { | |
1298 | mpc_atanh(result.data(), arg.data(), GMP_RNDN); | |
1299 | } | |
1300 | ||
1301 | template <unsigned Digits10> | |
1302 | inline void eval_conj(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1303 | { | |
1304 | mpc_conj(result.data(), arg.data(), GMP_RNDN); | |
1305 | } | |
1306 | ||
1307 | template <unsigned Digits10> | |
1308 | inline void eval_proj(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1309 | { | |
1310 | mpc_proj(result.data(), arg.data(), GMP_RNDN); | |
1311 | } | |
1312 | ||
1313 | template <unsigned Digits10> | |
1314 | inline void eval_real(mpfr_float_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1315 | { | |
1316 | mpfr_set_prec(result.data(), mpfr_get_prec(mpc_realref(arg.data()))); | |
1317 | mpfr_set(result.data(), mpc_realref(arg.data()), GMP_RNDN); | |
1318 | } | |
1319 | template <unsigned Digits10> | |
1320 | inline void eval_imag(mpfr_float_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg) | |
1321 | { | |
1322 | mpfr_set_prec(result.data(), mpfr_get_prec(mpc_imagref(arg.data()))); | |
1323 | mpfr_set(result.data(), mpc_imagref(arg.data()), GMP_RNDN); | |
1324 | } | |
1325 | ||
1326 | template <unsigned Digits10> | |
1327 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const mpfr_float_backend<Digits10>& arg) | |
1328 | { | |
1329 | mpfr_set(mpc_imagref(result.data()), arg.data(), GMP_RNDN); | |
1330 | } | |
1331 | ||
1332 | template <unsigned Digits10> | |
1333 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const mpfr_float_backend<Digits10>& arg) | |
1334 | { | |
1335 | mpfr_set(mpc_realref(result.data()), arg.data(), GMP_RNDN); | |
1336 | } | |
1337 | template <unsigned Digits10> | |
1338 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const gmp_int& arg) | |
1339 | { | |
1340 | mpfr_set_z(mpc_realref(result.data()), arg.data(), GMP_RNDN); | |
1341 | } | |
1342 | template <unsigned Digits10> | |
1343 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const gmp_rational& arg) | |
1344 | { | |
1345 | mpfr_set_q(mpc_realref(result.data()), arg.data(), GMP_RNDN); | |
1346 | } | |
1347 | template <unsigned Digits10> | |
1348 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const unsigned& arg) | |
1349 | { | |
1350 | mpfr_set_ui(mpc_realref(result.data()), arg, GMP_RNDN); | |
1351 | } | |
1352 | template <unsigned Digits10> | |
1353 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const unsigned long& arg) | |
1354 | { | |
1355 | mpfr_set_ui(mpc_realref(result.data()), arg, GMP_RNDN); | |
1356 | } | |
1357 | template <unsigned Digits10> | |
1358 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const int& arg) | |
1359 | { | |
1360 | mpfr_set_si(mpc_realref(result.data()), arg, GMP_RNDN); | |
1361 | } | |
1362 | template <unsigned Digits10> | |
1363 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const long& arg) | |
1364 | { | |
1365 | mpfr_set_si(mpc_realref(result.data()), arg, GMP_RNDN); | |
1366 | } | |
1367 | template <unsigned Digits10> | |
1368 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const float& arg) | |
1369 | { | |
1370 | mpfr_set_flt(mpc_realref(result.data()), arg, GMP_RNDN); | |
1371 | } | |
1372 | template <unsigned Digits10> | |
1373 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const double& arg) | |
1374 | { | |
1375 | mpfr_set_d(mpc_realref(result.data()), arg, GMP_RNDN); | |
1376 | } | |
1377 | template <unsigned Digits10> | |
1378 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const long double& arg) | |
1379 | { | |
1380 | mpfr_set_ld(mpc_realref(result.data()), arg, GMP_RNDN); | |
1381 | } | |
1382 | #if defined(BOOST_HAS_LONG_LONG) && defined(_MPFR_H_HAVE_INTMAX_T) | |
1383 | template <unsigned Digits10> | |
1384 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const unsigned long long& arg) | |
1385 | { | |
1386 | mpfr_set_uj(mpc_realref(result.data()), arg, GMP_RNDN); | |
1387 | } | |
1388 | template <unsigned Digits10> | |
1389 | inline void eval_set_real(mpc_complex_backend<Digits10>& result, const long long& arg) | |
1390 | { | |
1391 | mpfr_set_sj(mpc_realref(result.data()), arg, GMP_RNDN); | |
1392 | } | |
1393 | #endif | |
1394 | ||
1395 | template <unsigned Digits10> | |
1396 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const gmp_int& arg) | |
1397 | { | |
1398 | mpfr_set_z(mpc_imagref(result.data()), arg.data(), GMP_RNDN); | |
1399 | } | |
1400 | template <unsigned Digits10> | |
1401 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const gmp_rational& arg) | |
1402 | { | |
1403 | mpfr_set_q(mpc_imagref(result.data()), arg.data(), GMP_RNDN); | |
1404 | } | |
1405 | template <unsigned Digits10> | |
1406 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const unsigned& arg) | |
1407 | { | |
1408 | mpfr_set_ui(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1409 | } | |
1410 | template <unsigned Digits10> | |
1411 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const unsigned long& arg) | |
1412 | { | |
1413 | mpfr_set_ui(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1414 | } | |
1415 | template <unsigned Digits10> | |
1416 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const int& arg) | |
1417 | { | |
1418 | mpfr_set_si(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1419 | } | |
1420 | template <unsigned Digits10> | |
1421 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const long& arg) | |
1422 | { | |
1423 | mpfr_set_si(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1424 | } | |
1425 | template <unsigned Digits10> | |
1426 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const float& arg) | |
1427 | { | |
1428 | mpfr_set_flt(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1429 | } | |
1430 | template <unsigned Digits10> | |
1431 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const double& arg) | |
1432 | { | |
1433 | mpfr_set_d(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1434 | } | |
1435 | template <unsigned Digits10> | |
1436 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const long double& arg) | |
1437 | { | |
1438 | mpfr_set_ld(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1439 | } | |
1440 | #if defined(BOOST_HAS_LONG_LONG) && defined(_MPFR_H_HAVE_INTMAX_T) | |
1441 | template <unsigned Digits10> | |
1442 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const unsigned long long& arg) | |
1443 | { | |
1444 | mpfr_set_uj(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1445 | } | |
1446 | template <unsigned Digits10> | |
1447 | inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const long long& arg) | |
1448 | { | |
1449 | mpfr_set_sj(mpc_imagref(result.data()), arg, GMP_RNDN); | |
1450 | } | |
1451 | #endif | |
1452 | ||
1453 | template <unsigned Digits10> | |
1454 | inline std::size_t hash_value(const mpc_complex_backend<Digits10>& val) | |
1455 | { | |
1456 | std::size_t result = 0; | |
1457 | std::size_t len = val.data()[0].re[0]._mpfr_prec / mp_bits_per_limb; | |
1458 | if (val.data()[0].re[0]._mpfr_prec % mp_bits_per_limb) | |
1459 | ++len; | |
1460 | for (std::size_t i = 0; i < len; ++i) | |
1461 | boost::hash_combine(result, val.data()[0].re[0]._mpfr_d[i]); | |
1462 | boost::hash_combine(result, val.data()[0].re[0]._mpfr_exp); | |
1463 | boost::hash_combine(result, val.data()[0].re[0]._mpfr_sign); | |
1464 | ||
1465 | len = val.data()[0].im[0]._mpfr_prec / mp_bits_per_limb; | |
1466 | if (val.data()[0].im[0]._mpfr_prec % mp_bits_per_limb) | |
1467 | ++len; | |
1468 | for (std::size_t i = 0; i < len; ++i) | |
1469 | boost::hash_combine(result, val.data()[0].im[0]._mpfr_d[i]); | |
1470 | boost::hash_combine(result, val.data()[0].im[0]._mpfr_exp); | |
1471 | boost::hash_combine(result, val.data()[0].im[0]._mpfr_sign); | |
1472 | return result; | |
1473 | } | |
1474 | ||
1475 | } // namespace backends | |
1476 | ||
1477 | #ifdef BOOST_NO_SFINAE_EXPR | |
1478 | ||
1479 | namespace detail { | |
1480 | ||
1481 | template <unsigned D1, unsigned D2> | |
1482 | struct is_explicitly_convertible<backends::mpc_complex_backend<D1>, backends::mpc_complex_backend<D2> > : public mpl::true_ | |
1483 | {}; | |
1484 | ||
1485 | } // namespace detail | |
1486 | #endif | |
1487 | ||
1488 | namespace detail { | |
1489 | template <> | |
1490 | struct is_variable_precision<backends::mpc_complex_backend<0> > : public true_type | |
1491 | {}; | |
1492 | } // namespace detail | |
1493 | ||
1494 | template <> | |
1495 | struct number_category<detail::canonical<mpc_t, backends::mpc_complex_backend<0> >::type> : public mpl::int_<number_kind_floating_point> | |
1496 | {}; | |
1497 | ||
1498 | using boost::multiprecision::backends::mpc_complex_backend; | |
1499 | ||
1500 | typedef number<mpc_complex_backend<50> > mpc_complex_50; | |
1501 | typedef number<mpc_complex_backend<100> > mpc_complex_100; | |
1502 | typedef number<mpc_complex_backend<500> > mpc_complex_500; | |
1503 | typedef number<mpc_complex_backend<1000> > mpc_complex_1000; | |
1504 | typedef number<mpc_complex_backend<0> > mpc_complex; | |
1505 | ||
1506 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1507 | struct component_type<number<mpc_complex_backend<Digits10>, ExpressionTemplates> > | |
1508 | { | |
1509 | typedef number<mpfr_float_backend<Digits10>, ExpressionTemplates> type; | |
1510 | }; | |
1511 | ||
1512 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1513 | struct component_type<number<logged_adaptor<mpc_complex_backend<Digits10> >, ExpressionTemplates> > | |
1514 | { | |
1515 | typedef number<mpfr_float_backend<Digits10>, ExpressionTemplates> type; | |
1516 | }; | |
1517 | ||
1518 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1519 | struct complex_result_from_scalar<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > | |
1520 | { | |
1521 | typedef number<mpc_complex_backend<Digits10>, ExpressionTemplates> type; | |
1522 | }; | |
1523 | ||
1524 | } | |
1525 | ||
1526 | } // namespace boost::multiprecision | |
1527 | ||
1528 | #endif |