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