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>
12 #include <boost/multiprecision/detail/atomic.hpp>
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 
mpc_copy_precision(mpc_t dest,const mpc_t src)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 }
mpc_copy_precision(mpc_t dest,const mpc_t src1,const mpc_t src2)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 
mpc_complex_impboost::multiprecision::backends::detail::mpc_complex_imp74    mpc_complex_imp()
75    {
76       mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
77       mpc_set_ui(m_data, 0u, GMP_RNDN);
78    }
mpc_complex_impboost::multiprecision::backends::detail::mpc_complex_imp79    mpc_complex_imp(unsigned digits2)
80    {
81       mpc_init2(m_data, digits2);
82       mpc_set_ui(m_data, 0u, GMP_RNDN);
83    }
84 
mpc_complex_impboost::multiprecision::backends::detail::mpc_complex_imp85    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
mpc_complex_impboost::multiprecision::backends::detail::mpc_complex_imp92    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
operator =boost::multiprecision::backends::detail::mpc_complex_imp98    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
operator =boost::multiprecision::backends::detail::mpc_complex_imp109    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
operator =boost::multiprecision::backends::detail::mpc_complex_imp117    mpc_complex_imp& operator=(boost::ulong_long_type i)
118    {
119       if (m_data[0].re[0]._mpfr_d == 0)
120          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
121       mpc_set_uj(data(), i, GMP_RNDD);
122       return *this;
123    }
operator =boost::multiprecision::backends::detail::mpc_complex_imp124    mpc_complex_imp& operator=(boost::long_long_type i)
125    {
126       if (m_data[0].re[0]._mpfr_d == 0)
127          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
128       mpc_set_sj(data(), i, GMP_RNDD);
129       return *this;
130    }
131 #else
operator =boost::multiprecision::backends::detail::mpc_complex_imp132    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    }
operator =boost::multiprecision::backends::detail::mpc_complex_imp139    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
operator =boost::multiprecision::backends::detail::mpc_complex_imp148    mpc_complex_imp& operator=(unsigned long i)
149    {
150       if (m_data[0].re[0]._mpfr_d == 0)
151          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
152       mpc_set_ui(m_data, i, GMP_RNDN);
153       return *this;
154    }
operator =boost::multiprecision::backends::detail::mpc_complex_imp155    mpc_complex_imp& operator=(long i)
156    {
157       if (m_data[0].re[0]._mpfr_d == 0)
158          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
159       mpc_set_si(m_data, i, GMP_RNDN);
160       return *this;
161    }
operator =boost::multiprecision::backends::detail::mpc_complex_imp162    mpc_complex_imp& operator=(double d)
163    {
164       if (m_data[0].re[0]._mpfr_d == 0)
165          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
166       mpc_set_d(m_data, d, GMP_RNDN);
167       return *this;
168    }
operator =boost::multiprecision::backends::detail::mpc_complex_imp169    mpc_complex_imp& operator=(long double d)
170    {
171       if (m_data[0].re[0]._mpfr_d == 0)
172          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
173       mpc_set_ld(m_data, d, GMP_RNDN);
174       return *this;
175    }
operator =boost::multiprecision::backends::detail::mpc_complex_imp176    mpc_complex_imp& operator=(mpz_t i)
177    {
178       if (m_data[0].re[0]._mpfr_d == 0)
179          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
180       mpc_set_z(m_data, i, GMP_RNDN);
181       return *this;
182    }
operator =boost::multiprecision::backends::detail::mpc_complex_imp183    mpc_complex_imp& operator=(gmp_int i)
184    {
185       if (m_data[0].re[0]._mpfr_d == 0)
186          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
187       mpc_set_z(m_data, i.data(), GMP_RNDN);
188       return *this;
189    }
190 
operator =boost::multiprecision::backends::detail::mpc_complex_imp191    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)
196          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
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    }
swapboost::multiprecision::backends::detail::mpc_complex_imp246    void swap(mpc_complex_imp& o) BOOST_NOEXCEPT
247    {
248       mpc_swap(m_data, o.m_data);
249    }
strboost::multiprecision::backends::detail::mpc_complex_imp250    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    }
~mpc_complex_impboost::multiprecision::backends::detail::mpc_complex_imp264    ~mpc_complex_imp() BOOST_NOEXCEPT
265    {
266       if (m_data[0].re[0]._mpfr_d)
267          mpc_clear(m_data);
268    }
negateboost::multiprecision::backends::detail::mpc_complex_imp269    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    }
compareboost::multiprecision::backends::detail::mpc_complex_imp274    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    }
compareboost::multiprecision::backends::detail::mpc_complex_imp279    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    }
compareboost::multiprecision::backends::detail::mpc_complex_imp284    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    }
compareboost::multiprecision::backends::detail::mpc_complex_imp289    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>
compareboost::multiprecision::backends::detail::mpc_complex_imp302    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    }
databoost::multiprecision::backends::detail::mpc_complex_imp308    mpc_t& data() BOOST_NOEXCEPT
309    {
310       BOOST_ASSERT(m_data[0].re[0]._mpfr_d);
311       return m_data;
312    }
databoost::multiprecision::backends::detail::mpc_complex_imp313    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;
get_default_precisionboost::multiprecision::backends::detail::mpc_complex_imp321    static boost::multiprecision::detail::precision_type& get_default_precision() BOOST_NOEXCEPT
322    {
323       static boost::multiprecision::detail::precision_type val(BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION);
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 {
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend333    mpc_complex_backend() : detail::mpc_complex_imp<digits10>() {}
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend334    mpc_complex_backend(const mpc_complex_backend& o) : detail::mpc_complex_imp<digits10>(o) {}
335 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend336    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend340    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend346    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend352    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend358    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend363    mpc_complex_backend(const mpc_t val)
364        : detail::mpc_complex_imp<digits10>()
365    {
366       mpc_set(this->m_data, val, GMP_RNDN);
367    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend368    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend373    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend378    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend383    mpc_complex_backend(mpz_srcptr val) : detail::mpc_complex_imp<digits10>()
384    {
385       mpc_set_z(this->m_data, val, GMP_RNDN);
386    }
operator =boost::multiprecision::backends::mpc_complex_backend387    mpc_complex_backend& operator=(mpz_srcptr val)
388    {
389       mpc_set_z(this->m_data, val, GMP_RNDN);
390       return *this;
391    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend392    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    }
operator =boost::multiprecision::backends::mpc_complex_backend396    mpc_complex_backend& operator=(gmp_int const& val)
397    {
398       mpc_set_z(this->m_data, val.data(), GMP_RNDN);
399       return *this;
400    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend401    mpc_complex_backend(mpf_srcptr val) : detail::mpc_complex_imp<digits10>()
402    {
403       mpc_set_f(this->m_data, val, GMP_RNDN);
404    }
operator =boost::multiprecision::backends::mpc_complex_backend405    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend411    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>
operator =boost::multiprecision::backends::mpc_complex_backend416    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend421    mpc_complex_backend(mpq_srcptr val) : detail::mpc_complex_imp<digits10>()
422    {
423       mpc_set_q(this->m_data, val, GMP_RNDN);
424    }
operator =boost::multiprecision::backends::mpc_complex_backend425    mpc_complex_backend& operator=(mpq_srcptr val)
426    {
427       mpc_set_q(this->m_data, val, GMP_RNDN);
428       return *this;
429    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend430    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    }
operator =boost::multiprecision::backends::mpc_complex_backend434    mpc_complex_backend& operator=(gmp_rational const& val)
435    {
436       mpc_set_q(this->m_data, val.data(), GMP_RNDN);
437       return *this;
438    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend439    mpc_complex_backend(mpfr_srcptr val) : detail::mpc_complex_imp<digits10>()
440    {
441       mpc_set_fr(this->m_data, val, GMP_RNDN);
442    }
operator =boost::multiprecision::backends::mpc_complex_backend443    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend449    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>
operator =boost::multiprecision::backends::mpc_complex_backend454    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    }
operator =boost::multiprecision::backends::mpc_complex_backend459    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
operator =boost::multiprecision::backends::mpc_complex_backend465    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>
operator =boost::multiprecision::backends::mpc_complex_backend472    mpc_complex_backend& operator=(const V& v)
473    {
474       *static_cast<detail::mpc_complex_imp<digits10>*>(this) = v;
475       return *this;
476    }
operator =boost::multiprecision::backends::mpc_complex_backend477    mpc_complex_backend& operator=(const mpc_t val)
478    {
479       mpc_set(this->m_data, val, GMP_RNDN);
480       return *this;
481    }
operator =boost::multiprecision::backends::mpc_complex_backend482    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    }
operator =boost::multiprecision::backends::mpc_complex_backend487    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    }
operator =boost::multiprecision::backends::mpc_complex_backend492    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>
operator =boost::multiprecision::backends::mpc_complex_backend499    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 {
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend509    mpc_complex_backend() : detail::mpc_complex_imp<0>() {}
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend510    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend515    mpc_complex_backend(const mpc_complex_backend& o) : detail::mpc_complex_imp<0>(o) {}
516 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend517    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
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend520    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend526    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend532    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend537    mpc_complex_backend(mpz_srcptr val) : detail::mpc_complex_imp<0>()
538    {
539       mpc_set_z(this->m_data, val, GMP_RNDN);
540    }
operator =boost::multiprecision::backends::mpc_complex_backend541    mpc_complex_backend& operator=(mpz_srcptr val)
542    {
543       mpc_set_z(this->m_data, val, GMP_RNDN);
544       return *this;
545    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend546    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    }
operator =boost::multiprecision::backends::mpc_complex_backend550    mpc_complex_backend& operator=(gmp_int const& val)
551    {
552       mpc_set_z(this->m_data, val.data(), GMP_RNDN);
553       return *this;
554    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend555    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    }
operator =boost::multiprecision::backends::mpc_complex_backend559    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend571    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>
operator =boost::multiprecision::backends::mpc_complex_backend576    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend587    mpc_complex_backend(mpq_srcptr val) : detail::mpc_complex_imp<0>()
588    {
589       mpc_set_q(this->m_data, val, GMP_RNDN);
590    }
operator =boost::multiprecision::backends::mpc_complex_backend591    mpc_complex_backend& operator=(mpq_srcptr val)
592    {
593       mpc_set_q(this->m_data, val, GMP_RNDN);
594       return *this;
595    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend596    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    }
operator =boost::multiprecision::backends::mpc_complex_backend600    mpc_complex_backend& operator=(gmp_rational const& val)
601    {
602       mpc_set_q(this->m_data, val.data(), GMP_RNDN);
603       return *this;
604    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend605    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    }
operator =boost::multiprecision::backends::mpc_complex_backend609    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend620    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend625    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    }
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend630    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend637    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>
mpc_complex_backendboost::multiprecision::backends::mpc_complex_backend646    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 
operator =boost::multiprecision::backends::mpc_complex_backend652    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
operator =boost::multiprecision::backends::mpc_complex_backend662    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>
operator =boost::multiprecision::backends::mpc_complex_backend669    mpc_complex_backend& operator=(const V& v)
670    {
671       *static_cast<detail::mpc_complex_imp<0>*>(this) = v;
672       return *this;
673    }
operator =boost::multiprecision::backends::mpc_complex_backend674    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>
operator =boost::multiprecision::backends::mpc_complex_backend681    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>
operator =boost::multiprecision::backends::mpc_complex_backend688    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    }
operator =boost::multiprecision::backends::mpc_complex_backend694    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    }
operator =boost::multiprecision::backends::mpc_complex_backend699    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    }
operator =boost::multiprecision::backends::mpc_complex_backend704    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    }
default_precisionboost::multiprecision::backends::mpc_complex_backend709    static unsigned default_precision() BOOST_NOEXCEPT
710    {
711       return get_default_precision();
712    }
default_precisionboost::multiprecision::backends::mpc_complex_backend713    static void default_precision(unsigned v) BOOST_NOEXCEPT
714    {
715       get_default_precision() = v;
716    }
precisionboost::multiprecision::backends::mpc_complex_backend717    unsigned precision() const BOOST_NOEXCEPT
718    {
719       return multiprecision::detail::digits2_2_10(mpc_get_prec(this->m_data));
720    }
precisionboost::multiprecision::backends::mpc_complex_backend721    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>
eval_eq(const mpc_complex_backend<digits10> & a,const T & b)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>
eval_lt(const mpc_complex_backend<digits10> & a,const T & b)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>
eval_gt(const mpc_complex_backend<digits10> & a,const T & b)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>
eval_add(mpc_complex_backend<D1> & result,const mpc_complex_backend<D2> & o)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>
eval_add(mpc_complex_backend<D1> & result,const mpfr_float_backend<D2> & o)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>
eval_subtract(mpc_complex_backend<D1> & result,const mpc_complex_backend<D2> & o)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>
eval_subtract(mpc_complex_backend<D1> & result,const mpfr_float_backend<D2> & o)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>
eval_multiply(mpc_complex_backend<D1> & result,const mpc_complex_backend<D2> & o)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>
eval_multiply(mpc_complex_backend<D1> & result,const mpfr_float_backend<D2> & o)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>
eval_divide(mpc_complex_backend<D1> & result,const mpc_complex_backend<D2> & o)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>
eval_divide(mpc_complex_backend<D1> & result,const mpfr_float_backend<D2> & o)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>
eval_add(mpc_complex_backend<digits10> & result,unsigned long i)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>
eval_subtract(mpc_complex_backend<digits10> & result,unsigned long i)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>
eval_multiply(mpc_complex_backend<digits10> & result,unsigned long i)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>
eval_divide(mpc_complex_backend<digits10> & result,unsigned long i)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>
eval_add(mpc_complex_backend<digits10> & result,long i)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>
eval_subtract(mpc_complex_backend<digits10> & result,long i)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>
eval_multiply(mpc_complex_backend<digits10> & result,long i)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>
eval_divide(mpc_complex_backend<digits10> & result,long i)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>
eval_add(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_add(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpfr_float_backend<D3> & y)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>
eval_add(mpc_complex_backend<D1> & a,const mpfr_float_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_add(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,unsigned long y)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>
eval_add(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,long y)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>
eval_add(mpc_complex_backend<D1> & a,unsigned long x,const mpc_complex_backend<D2> & y)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>
eval_add(mpc_complex_backend<D1> & a,long x,const mpc_complex_backend<D2> & y)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>
eval_subtract(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_subtract(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpfr_float_backend<D3> & y)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>
eval_subtract(mpc_complex_backend<D1> & a,const mpfr_float_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_subtract(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,unsigned long y)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>
eval_subtract(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,long y)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>
eval_subtract(mpc_complex_backend<D1> & a,unsigned long x,const mpc_complex_backend<D2> & y)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>
eval_subtract(mpc_complex_backend<D1> & a,long x,const mpc_complex_backend<D2> & y)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>
eval_multiply(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_multiply(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpfr_float_backend<D3> & y)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>
eval_multiply(mpc_complex_backend<D1> & a,const mpfr_float_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_multiply(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,unsigned long y)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>
eval_multiply(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,long y)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>
eval_multiply(mpc_complex_backend<D1> & a,unsigned long x,const mpc_complex_backend<D2> & y)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>
eval_multiply(mpc_complex_backend<D1> & a,long x,const mpc_complex_backend<D2> & y)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>
eval_divide(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_divide(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,const mpfr_float_backend<D3> & y)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>
eval_divide(mpc_complex_backend<D1> & a,const mpfr_float_backend<D2> & x,const mpc_complex_backend<D3> & y)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>
eval_divide(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,unsigned long y)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>
eval_divide(mpc_complex_backend<D1> & a,const mpc_complex_backend<D2> & x,long y)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>
eval_divide(mpc_complex_backend<D1> & a,unsigned long x,const mpc_complex_backend<D2> & y)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>
eval_divide(mpc_complex_backend<D1> & a,long x,const mpc_complex_backend<D2> & y)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>
eval_is_zero(const mpc_complex_backend<digits10> & val)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>
eval_get_sign(const mpc_complex_backend<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>
eval_convert_to(unsigned long * result,const mpc_complex_backend<digits10> & val)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>
eval_convert_to(long * result,const mpc_complex_backend<digits10> & val)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>
eval_convert_to(boost::ulong_long_type * result,const mpc_complex_backend<digits10> & val)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>
eval_convert_to(boost::long_long_type * result,const mpc_complex_backend<digits10> & val)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>
eval_convert_to(double * result,const mpc_complex_backend<digits10> & val)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>
eval_convert_to(long double * result,const mpc_complex_backend<digits10> & val)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>
assign_components(mpc_complex_backend<D1> & result,const mpfr_float_backend<D2,AllocationType> & a,const mpfr_float_backend<D2,AllocationType> & b)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>
assign_components(mpc_complex_backend<D1> & result,unsigned long a,unsigned long b)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>
assign_components(mpc_complex_backend<D1> & result,long a,long b)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>
assign_components(mpc_complex_backend<D1> & result,unsigned long long a,unsigned long long b)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>
assign_components(mpc_complex_backend<D1> & result,long long a,long long b)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>
assign_components(mpc_complex_backend<D1> & result,double a,double b)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>
assign_components(mpc_complex_backend<D1> & result,long double a,long double b)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>
eval_sqrt(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & val)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>
eval_pow(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & b,const mpc_complex_backend<Digits10> & e)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>
eval_exp(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_log(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_log10(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_sin(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_cos(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_tan(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_asin(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_acos(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_atan(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_sinh(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_cosh(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_tanh(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_asinh(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_acosh(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_atanh(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_conj(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_proj(mpc_complex_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_real(mpfr_float_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_imag(mpfr_float_backend<Digits10> & result,const mpc_complex_backend<Digits10> & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const mpfr_float_backend<Digits10> & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const mpfr_float_backend<Digits10> & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const gmp_int & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const gmp_rational & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const unsigned & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const unsigned long & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const int & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const long & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const float & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const double & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const long double & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const unsigned long long & arg)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>
eval_set_real(mpc_complex_backend<Digits10> & result,const long long & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const gmp_int & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const gmp_rational & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const unsigned & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const unsigned long & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const int & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const long & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const float & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const double & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const long double & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const unsigned long long & arg)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>
eval_set_imag(mpc_complex_backend<Digits10> & result,const long long & arg)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>
hash_value(const mpc_complex_backend<Digits10> & val)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
1529