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