Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:32

0001 ///////////////////////////////////////////////////////////////////////////////
0002 //  Copyright 2018 John Maddock. Distributed under the Boost
0003 //  Software License, Version 1.0. (See accompanying file
0004 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_MP_MPC_HPP
0007 #define BOOST_MP_MPC_HPP
0008 
0009 #include <cstdint>
0010 #include <boost/multiprecision/detail/standalone_config.hpp>
0011 #include <boost/multiprecision/detail/fpclassify.hpp>
0012 #include <boost/multiprecision/number.hpp>
0013 #include <boost/multiprecision/detail/digits.hpp>
0014 #include <boost/multiprecision/detail/atomic.hpp>
0015 #include <boost/multiprecision/traits/is_variable_precision.hpp>
0016 #include <boost/multiprecision/mpfr.hpp>
0017 #include <boost/multiprecision/detail/hash.hpp>
0018 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0019 #include <boost/multiprecision/detail/assert.hpp>
0020 #include <mpc.h>
0021 #include <cmath>
0022 #include <algorithm>
0023 #include <complex>
0024 
0025 #ifndef BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION
0026 #define BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION 20
0027 #endif
0028 
0029 namespace boost {
0030 namespace multiprecision {
0031 
0032 template <unsigned digits10>
0033 struct number_category<backends::mpc_complex_backend<digits10> > : public std::integral_constant<int, number_kind_complex>
0034 {};
0035 
0036 namespace backends {
0037 
0038 namespace detail {
0039 
0040 inline void mpc_copy_precision(mpc_t dest, const mpc_t src)
0041 {
0042    mpfr_prec_t p_dest = mpc_get_prec(dest);
0043    mpfr_prec_t p_src  = mpc_get_prec(src);
0044    if (p_dest != p_src)
0045       mpc_set_prec(dest, p_src);
0046 }
0047 inline void mpc_copy_precision(mpc_t dest, const mpc_t src1, const mpc_t src2)
0048 {
0049    mpfr_prec_t p_dest = mpc_get_prec(dest);
0050    mpfr_prec_t p_src1 = mpc_get_prec(src1);
0051    mpfr_prec_t p_src2 = mpc_get_prec(src2);
0052    if (p_src2 > p_src1)
0053       p_src1 = p_src2;
0054    if (p_dest != p_src1)
0055       mpc_set_prec(dest, p_src1);
0056 }
0057 
0058 template <unsigned digits10>
0059 struct mpc_complex_imp
0060 {
0061 #ifdef BOOST_HAS_LONG_LONG
0062    using signed_types = std::tuple<long, long long>          ;
0063    using unsigned_types = std::tuple<unsigned long, unsigned long long>;
0064 #else
0065    using signed_types = std::tuple<long>         ;
0066    using unsigned_types = std::tuple<unsigned long>;
0067 #endif
0068    using float_types = std::tuple<double, long double>;
0069    using exponent_type = long                          ;
0070 
0071    mpc_complex_imp()
0072    {
0073       mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0074       mpc_set_ui(m_data, 0u, GMP_RNDN);
0075    }
0076    mpc_complex_imp(unsigned digits2)
0077    {
0078       mpc_init2(m_data, digits2);
0079       mpc_set_ui(m_data, 0u, GMP_RNDN);
0080    }
0081 
0082    mpc_complex_imp(const mpc_complex_imp& o)
0083    {
0084       mpc_init2(m_data, preserve_source_precision() ? mpc_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0085       if (o.m_data[0].re[0]._mpfr_d)
0086          mpc_set(m_data, o.m_data, GMP_RNDN);
0087    }
0088    // rvalue copy
0089    mpc_complex_imp(mpc_complex_imp&& o) noexcept
0090    {
0091       mpfr_prec_t binary_default_precision = boost::multiprecision::detail::digits10_2_2(get_default_precision());
0092       if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpc_get_prec(o.data()) == binary_default_precision))
0093       {
0094          m_data[0] = o.m_data[0];
0095          o.m_data[0].re[0]._mpfr_d = nullptr;
0096       }
0097       else
0098       {
0099          // NOTE: C allocation interface must not throw:
0100          mpc_init2(m_data, binary_default_precision);
0101          if (o.m_data[0].re[0]._mpfr_d)
0102             mpc_set(m_data, o.m_data, GMP_RNDN);
0103       }
0104    }
0105    mpc_complex_imp& operator=(const mpc_complex_imp& o)
0106    {
0107       if ((o.m_data[0].re[0]._mpfr_d) && (this != &o))
0108       {
0109          if (m_data[0].re[0]._mpfr_d == nullptr)
0110             mpc_init2(m_data, preserve_source_precision() ? mpc_get_prec(o.m_data) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0111          else if (preserve_source_precision() && (mpc_get_prec(o.data()) != mpc_get_prec(data())))
0112          {
0113             mpc_set_prec(m_data, mpc_get_prec(o.m_data));
0114          }
0115          mpc_set(m_data, o.m_data, GMP_RNDN);
0116       }
0117       return *this;
0118    }
0119    // rvalue assign
0120    mpc_complex_imp& operator=(mpc_complex_imp&& o) noexcept
0121    {
0122       if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpc_get_prec(o.data()) == mpc_get_prec(data())))
0123          mpc_swap(m_data, o.m_data);
0124       else
0125          *this = static_cast<const mpc_complex_imp&>(o);
0126       return *this;
0127    }
0128 #ifdef BOOST_HAS_LONG_LONG
0129 #ifdef _MPFR_H_HAVE_INTMAX_T
0130    mpc_complex_imp& operator=(unsigned long long i)
0131    {
0132       if (m_data[0].re[0]._mpfr_d == nullptr)
0133          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0134       mpc_set_uj(data(), i, GMP_RNDN);
0135       return *this;
0136    }
0137    mpc_complex_imp& operator=(long long i)
0138    {
0139       if (m_data[0].re[0]._mpfr_d == nullptr)
0140          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0141       mpc_set_sj(data(), i, GMP_RNDN);
0142       return *this;
0143    }
0144 #else
0145    mpc_complex_imp& operator=(unsigned long long i)
0146    {
0147       mpfr_float_backend<digits10> f(0uL, mpc_get_prec(m_data));
0148       f = i;
0149       mpc_set_fr(this->data(), f.data(), GMP_RNDN);
0150       return *this;
0151    }
0152    mpc_complex_imp& operator=(long long i)
0153    {
0154       mpfr_float_backend<digits10> f(0uL, mpc_get_prec(m_data));
0155       f = i;
0156       mpc_set_fr(this->data(), f.data(), GMP_RNDN);
0157       return *this;
0158    }
0159 #endif
0160 #endif
0161    mpc_complex_imp& operator=(unsigned long i)
0162    {
0163       if (m_data[0].re[0]._mpfr_d == nullptr)
0164          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0165       mpc_set_ui(m_data, i, GMP_RNDN);
0166       return *this;
0167    }
0168    mpc_complex_imp& operator=(long i)
0169    {
0170       if (m_data[0].re[0]._mpfr_d == nullptr)
0171          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0172       mpc_set_si(m_data, i, GMP_RNDN);
0173       return *this;
0174    }
0175    mpc_complex_imp& operator=(double d)
0176    {
0177       if (m_data[0].re[0]._mpfr_d == nullptr)
0178          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0179       mpc_set_d(m_data, d, GMP_RNDN);
0180       return *this;
0181    }
0182    mpc_complex_imp& operator=(long double d)
0183    {
0184       if (m_data[0].re[0]._mpfr_d == nullptr)
0185          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0186       mpc_set_ld(m_data, d, GMP_RNDN);
0187       return *this;
0188    }
0189    mpc_complex_imp& operator=(mpz_t i)
0190    {
0191       if (m_data[0].re[0]._mpfr_d == nullptr)
0192          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0193       mpc_set_z(m_data, i, GMP_RNDN);
0194       return *this;
0195    }
0196    mpc_complex_imp& operator=(gmp_int i)
0197    {
0198       if (m_data[0].re[0]._mpfr_d == nullptr)
0199          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0200       mpc_set_z(m_data, i.data(), GMP_RNDN);
0201       return *this;
0202    }
0203 #ifdef BOOST_HAS_INT128
0204    mpc_complex_imp& operator=(int128_type val)
0205    {
0206       gmp_int i;
0207       i            = val;
0208       return *this = i.data();
0209    }
0210    mpc_complex_imp& operator=(uint128_type val)
0211    {
0212       gmp_int i;
0213       i            = val;
0214       return *this = i.data();
0215    }
0216 #endif
0217 #ifdef BOOST_HAS_FLOAT128
0218    mpc_complex_imp& operator=(float128_type val)
0219    {
0220       mpfr_float_backend<digits10> f;
0221       f            = val;
0222       mpc_set_fr(this->m_data, f.data(), GMP_RNDN);
0223       return *this;
0224    }
0225 #endif
0226 
0227    mpc_complex_imp& operator=(const char* s)
0228    {
0229       using default_ops::eval_fpclassify;
0230 
0231       if (m_data[0].re[0]._mpfr_d == nullptr)
0232          mpc_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0233 
0234       mpfr_float_backend<digits10> a(0uL, mpc_get_prec(m_data)), b(0uL, mpc_get_prec(m_data));
0235 
0236       if (s && (*s == '('))
0237       {
0238          std::string part;
0239          const char* p = ++s;
0240          while (*p && (*p != ',') && (*p != ')'))
0241             ++p;
0242          part.assign(s, p);
0243          if (part.size())
0244             a = part.c_str();
0245          else
0246             a = 0uL;
0247          s = p;
0248          if (*p && (*p != ')'))
0249          {
0250             ++p;
0251             while (*p && (*p != ')'))
0252                ++p;
0253             part.assign(s + 1, p);
0254          }
0255          else
0256             part.erase();
0257          if (part.size())
0258             b = part.c_str();
0259          else
0260             b = 0uL;
0261       }
0262       else
0263       {
0264          a = s;
0265          b = 0uL;
0266       }
0267 
0268       if (eval_fpclassify(a) == static_cast<int>(FP_NAN))
0269       {
0270          mpc_set_fr(this->data(), a.data(), GMP_RNDN);
0271       }
0272       else if (eval_fpclassify(b) == static_cast<int>(FP_NAN))
0273       {
0274          mpc_set_fr(this->data(), b.data(), GMP_RNDN);
0275       }
0276       else
0277       {
0278          mpc_set_fr_fr(m_data, a.data(), b.data(), GMP_RNDN);
0279       }
0280       return *this;
0281    }
0282    void swap(mpc_complex_imp& o) noexcept
0283    {
0284       mpc_swap(m_data, o.m_data);
0285    }
0286    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
0287    {
0288       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d);
0289 
0290       mpfr_float_backend<digits10> a(0uL, mpc_get_prec(m_data)), b(0uL, mpc_get_prec(m_data));
0291 
0292       mpc_real(a.data(), m_data, GMP_RNDN);
0293       mpc_imag(b.data(), m_data, GMP_RNDN);
0294 
0295       if (eval_is_zero(b))
0296          return a.str(digits, f);
0297 
0298       return "(" + a.str(digits, f) + "," + b.str(digits, f) + ")";
0299    }
0300    ~mpc_complex_imp() noexcept
0301    {
0302       if (m_data[0].re[0]._mpfr_d)
0303          mpc_clear(m_data);
0304    }
0305    void negate() noexcept
0306    {
0307       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d);
0308       mpc_neg(m_data, m_data, GMP_RNDN);
0309    }
0310    int compare(const mpc_complex_imp& o) const noexcept
0311    {
0312       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d && o.m_data[0].re[0]._mpfr_d);
0313       return mpc_cmp(m_data, o.m_data);
0314    }
0315    int compare(const mpc_complex_backend<digits10>& o) const noexcept
0316    {
0317       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d && o.m_data[0].re[0]._mpfr_d);
0318       return mpc_cmp(m_data, o.data());
0319    }
0320    int compare(long int i) const noexcept
0321    {
0322       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d);
0323       return mpc_cmp_si(m_data, i);
0324    }
0325    int compare(unsigned long int i) const noexcept
0326    {
0327       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d);
0328       constexpr const unsigned long int max_val = (std::numeric_limits<long>::max)();
0329       if (i > max_val)
0330       {
0331          mpc_complex_imp d(mpc_get_prec(m_data));
0332          d = i;
0333          return compare(d);
0334       }
0335       return mpc_cmp_si(m_data, static_cast<long>(i));
0336    }
0337    template <class V>
0338    int compare(const V& v) const noexcept
0339    {
0340       mpc_complex_imp d(mpc_get_prec(m_data));
0341       d = v;
0342       return compare(d);
0343    }
0344    mpc_t& data() noexcept
0345    {
0346       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d);
0347       return m_data;
0348    }
0349    const mpc_t& data() const noexcept
0350    {
0351       BOOST_MP_ASSERT(m_data[0].re[0]._mpfr_d);
0352       return m_data;
0353    }
0354 
0355  protected:
0356    mpc_t            m_data;
0357    static boost::multiprecision::detail::precision_type& get_global_default_precision() noexcept
0358    {
0359       static boost::multiprecision::detail::precision_type val(BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION);
0360       return val;
0361    }
0362    static unsigned& get_default_precision() noexcept
0363    {
0364       static BOOST_MP_THREAD_LOCAL unsigned val(get_global_default_precision());
0365       return val;
0366    }
0367 #ifndef BOOST_MT_NO_ATOMIC_INT
0368    static std::atomic<variable_precision_options>& get_global_default_options() noexcept
0369 #else
0370    static variable_precision_options& get_global_default_options() noexcept
0371 #endif
0372    {
0373 #ifndef BOOST_MT_NO_ATOMIC_INT
0374       static std::atomic<variable_precision_options> val{variable_precision_options::preserve_related_precision};
0375 #else
0376       static variable_precision_options val{variable_precision_options::preserve_related_precision};
0377 #endif
0378       return val;
0379    }
0380    static variable_precision_options& get_default_options() noexcept
0381    {
0382       static BOOST_MP_THREAD_LOCAL variable_precision_options val(get_global_default_options());
0383       return val;
0384    }
0385    static bool preserve_source_precision() noexcept
0386    {
0387       return get_default_options() >= variable_precision_options::preserve_source_precision;
0388    }
0389    static bool preserve_component_precision() noexcept
0390    {
0391       return get_default_options() >= variable_precision_options::preserve_component_precision;
0392    }
0393    static bool preserve_related_precision() noexcept
0394    {
0395       return get_default_options() >= variable_precision_options::preserve_related_precision;
0396    }
0397    static bool preserve_all_precision() noexcept
0398    {
0399       return get_default_options() >= variable_precision_options::preserve_all_precision;
0400    }
0401 };
0402 
0403 } // namespace detail
0404 
0405 template <unsigned digits10>
0406 struct mpc_complex_backend : public detail::mpc_complex_imp<digits10>
0407 {
0408    mpc_complex_backend() : detail::mpc_complex_imp<digits10>() {}
0409    mpc_complex_backend(const mpc_complex_backend& o) : detail::mpc_complex_imp<digits10>(o) {}
0410    // rvalue copy
0411    mpc_complex_backend(mpc_complex_backend&& o) : detail::mpc_complex_imp<digits10>(static_cast<detail::mpc_complex_imp<digits10>&&>(o))
0412    {}
0413    template <unsigned D>
0414    mpc_complex_backend(const mpc_complex_backend<D>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0415        : detail::mpc_complex_imp<digits10>()
0416    {
0417       mpc_set(this->m_data, val.data(), GMP_RNDN);
0418    }
0419    template <unsigned D>
0420    explicit mpc_complex_backend(const mpc_complex_backend<D>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
0421        : detail::mpc_complex_imp<digits10>()
0422    {
0423       mpc_set(this->m_data, val.data(), GMP_RNDN);
0424    }
0425    mpc_complex_backend(const mpc_t val)
0426        : detail::mpc_complex_imp<digits10>()
0427    {
0428       mpc_set(this->m_data, val, GMP_RNDN);
0429    }
0430    mpc_complex_backend(const std::complex<float>& val)
0431        : detail::mpc_complex_imp<digits10>()
0432    {
0433       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0434    }
0435    mpc_complex_backend(const std::complex<double>& val)
0436        : detail::mpc_complex_imp<digits10>()
0437    {
0438       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0439    }
0440    mpc_complex_backend(const std::complex<long double>& val)
0441        : detail::mpc_complex_imp<digits10>()
0442    {
0443       mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN);
0444    }
0445    mpc_complex_backend(mpz_srcptr val) : detail::mpc_complex_imp<digits10>()
0446    {
0447       mpc_set_z(this->m_data, val, GMP_RNDN);
0448    }
0449    mpc_complex_backend& operator=(mpz_srcptr val)
0450    {
0451       mpc_set_z(this->m_data, val, GMP_RNDN);
0452       return *this;
0453    }
0454    mpc_complex_backend(gmp_int const& val) : detail::mpc_complex_imp<digits10>()
0455    {
0456       mpc_set_z(this->m_data, val.data(), GMP_RNDN);
0457    }
0458    mpc_complex_backend& operator=(gmp_int const& val)
0459    {
0460       mpc_set_z(this->m_data, val.data(), GMP_RNDN);
0461       return *this;
0462    }
0463    mpc_complex_backend(mpf_srcptr val) : detail::mpc_complex_imp<digits10>()
0464    {
0465       mpc_set_f(this->m_data, val, GMP_RNDN);
0466    }
0467    mpc_complex_backend& operator=(mpf_srcptr val)
0468    {
0469       mpc_set_f(this->m_data, val, GMP_RNDN);
0470       return *this;
0471    }
0472    template <unsigned D10>
0473    mpc_complex_backend(gmp_float<D10> const& val) : detail::mpc_complex_imp<digits10>()
0474    {
0475       mpc_set_f(this->m_data, val.data(), GMP_RNDN);
0476    }
0477    template <unsigned D10>
0478    mpc_complex_backend& operator=(gmp_float<D10> const& val)
0479    {
0480       mpc_set_f(this->m_data, val.data(), GMP_RNDN);
0481       return *this;
0482    }
0483    mpc_complex_backend(mpq_srcptr val) : detail::mpc_complex_imp<digits10>()
0484    {
0485       mpc_set_q(this->m_data, val, GMP_RNDN);
0486    }
0487    mpc_complex_backend& operator=(mpq_srcptr val)
0488    {
0489       mpc_set_q(this->m_data, val, GMP_RNDN);
0490       return *this;
0491    }
0492    mpc_complex_backend(gmp_rational const& val) : detail::mpc_complex_imp<digits10>()
0493    {
0494       mpc_set_q(this->m_data, val.data(), GMP_RNDN);
0495    }
0496    mpc_complex_backend& operator=(gmp_rational const& val)
0497    {
0498       mpc_set_q(this->m_data, val.data(), GMP_RNDN);
0499       return *this;
0500    }
0501    mpc_complex_backend(mpfr_srcptr val) : detail::mpc_complex_imp<digits10>()
0502    {
0503       mpc_set_fr(this->m_data, val, GMP_RNDN);
0504    }
0505    mpc_complex_backend& operator=(mpfr_srcptr val)
0506    {
0507       mpc_set_fr(this->m_data, val, GMP_RNDN);
0508       return *this;
0509    }
0510    template <unsigned D10, mpfr_allocation_type AllocationType>
0511    mpc_complex_backend(mpfr_float_backend<D10, AllocationType> const& val, typename std::enable_if<D10 <= digits10>::type* = nullptr) : detail::mpc_complex_imp<digits10>()
0512    {
0513       mpc_set_fr(this->m_data, val.data(), GMP_RNDN);
0514    }
0515    template <unsigned D10, mpfr_allocation_type AllocationType>
0516    explicit mpc_complex_backend(mpfr_float_backend<D10, AllocationType> const& val, typename std::enable_if<!(D10 <= digits10)>::type* = nullptr) : detail::mpc_complex_imp<digits10>()
0517    {
0518       mpc_set_fr(this->m_data, val.data(), GMP_RNDN);
0519    }
0520    template <unsigned D10, mpfr_allocation_type AllocationType>
0521    mpc_complex_backend& operator=(mpfr_float_backend<D10, AllocationType> const& val)
0522    {
0523       mpc_set_fr(this->m_data, val.data(), GMP_RNDN);
0524       return *this;
0525    }
0526    mpc_complex_backend& operator=(const mpc_complex_backend& o)
0527    {
0528       *static_cast<detail::mpc_complex_imp<digits10>*>(this) = static_cast<detail::mpc_complex_imp<digits10> const&>(o);
0529       return *this;
0530    }
0531    // rvalue assign
0532    mpc_complex_backend& operator=(mpc_complex_backend&& o) noexcept
0533    {
0534       *static_cast<detail::mpc_complex_imp<digits10>*>(this) = static_cast<detail::mpc_complex_imp<digits10>&&>(o);
0535       return *this;
0536    }
0537    template <class V>
0538    typename std::enable_if<std::is_assignable<detail::mpc_complex_imp<digits10>, V>::value, mpc_complex_backend&>::type operator=(const V& v)
0539    {
0540       *static_cast<detail::mpc_complex_imp<digits10>*>(this) = v;
0541       return *this;
0542    }
0543    mpc_complex_backend& operator=(const mpc_t val)
0544    {
0545       mpc_set(this->m_data, val, GMP_RNDN);
0546       return *this;
0547    }
0548    mpc_complex_backend& operator=(const std::complex<float>& val)
0549    {
0550       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0551       return *this;
0552    }
0553    mpc_complex_backend& operator=(const std::complex<double>& val)
0554    {
0555       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0556       return *this;
0557    }
0558    mpc_complex_backend& operator=(const std::complex<long double>& val)
0559    {
0560       mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN);
0561       return *this;
0562    }
0563    // We don't change our precision here, this is a fixed precision type:
0564    template <unsigned D>
0565    mpc_complex_backend& operator=(const mpc_complex_backend<D>& val)
0566    {
0567       mpc_set(this->m_data, val.data(), GMP_RNDN);
0568       return *this;
0569    }
0570 };
0571 
0572 template <>
0573 struct mpc_complex_backend<0> : public detail::mpc_complex_imp<0>
0574 {
0575    mpc_complex_backend() : detail::mpc_complex_imp<0>() {}
0576    mpc_complex_backend(const mpc_t val)
0577        : detail::mpc_complex_imp<0>(mpc_get_prec(val))
0578    {
0579       mpc_set(this->m_data, val, GMP_RNDN);
0580    }
0581    mpc_complex_backend(const mpc_complex_backend& o) : detail::mpc_complex_imp<0>(o) {}
0582    // rvalue copy
0583    mpc_complex_backend(mpc_complex_backend&& o) noexcept : detail::mpc_complex_imp<0>(static_cast<detail::mpc_complex_imp<0>&&>(o))
0584    {}
0585    mpc_complex_backend(const mpc_complex_backend& o, unsigned digits10)
0586        : detail::mpc_complex_imp<0>(multiprecision::detail::digits10_2_2(digits10))
0587    {
0588       mpc_set(this->m_data, o.data(), GMP_RNDN);
0589    }
0590    template <unsigned D>
0591    mpc_complex_backend(const mpc_complex_backend<D>& val)
0592        : detail::mpc_complex_imp<0>(preserve_related_precision() ? mpc_get_prec(val.data()) : multiprecision::detail::digits10_2_2(get_default_precision()))
0593    {
0594       mpc_set(this->m_data, val.data(), GMP_RNDN);
0595    }
0596    template <unsigned D>
0597    mpc_complex_backend(const mpfr_float_backend<D>& val)
0598        : detail::mpc_complex_imp<0>((D == 0 ? this->preserve_component_precision() : this->preserve_related_precision()) ? mpfr_get_prec(val.data()) : multiprecision::detail::digits10_2_2(this->get_default_precision()))
0599    {
0600       mpc_set_fr(this->m_data, val.data(), GMP_RNDN);
0601    }
0602    mpc_complex_backend(mpz_srcptr val) : detail::mpc_complex_imp<0>()
0603    {
0604       mpc_set_z(this->m_data, val, GMP_RNDN);
0605    }
0606    mpc_complex_backend& operator=(mpz_srcptr val)
0607    {
0608       mpc_set_z(this->m_data, val, GMP_RNDN);
0609       return *this;
0610    }
0611    mpc_complex_backend(gmp_int const& val) : detail::mpc_complex_imp<0>(preserve_all_precision() ? used_gmp_int_bits(val) : boost::multiprecision::detail::digits10_2_2(thread_default_precision()))
0612    {
0613       mpc_set_z(this->m_data, val.data(), GMP_RNDN);
0614    }
0615    mpc_complex_backend& operator=(gmp_int const& val)
0616    {
0617       if (this->m_data[0].im->_mpfr_d == nullptr)
0618       {
0619          unsigned requested_precision = this->thread_default_precision();
0620          if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
0621          {
0622             unsigned d2 = used_gmp_int_bits(val);
0623             unsigned d10 = 1 + multiprecision::detail::digits2_2_10(d2);
0624             if (d10 > requested_precision)
0625                requested_precision = d10;
0626          }
0627          mpc_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0628       }
0629       else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
0630       {
0631          unsigned requested_precision = this->thread_default_precision();
0632          unsigned d2 = used_gmp_int_bits(val);
0633          unsigned d10 = 1 + multiprecision::detail::digits2_2_10(d2);
0634          if (d10 > requested_precision)
0635             this->precision(d10);
0636       }
0637       mpc_set_z(this->m_data, val.data(), GMP_RNDN);
0638       return *this;
0639    }
0640    mpc_complex_backend(mpf_srcptr val) : detail::mpc_complex_imp<0>((unsigned)mpf_get_prec(val))
0641    {
0642       mpc_set_f(this->m_data, val, GMP_RNDN);
0643    }
0644    mpc_complex_backend& operator=(mpf_srcptr val)
0645    {
0646       if ((mp_bitcnt_t)mpc_get_prec(data()) != mpf_get_prec(val))
0647       {
0648          mpc_complex_backend t(val);
0649          t.swap(*this);
0650       }
0651       else
0652          mpc_set_f(this->m_data, val, GMP_RNDN);
0653       return *this;
0654    }
0655    template <unsigned digits10>
0656    mpc_complex_backend(gmp_float<digits10> const& val) : detail::mpc_complex_imp<0>(preserve_all_precision() ? (unsigned)mpf_get_prec(val.data()) : multiprecision::detail::digits10_2_2(get_default_precision()))
0657    {
0658       mpc_set_f(this->m_data, val.data(), GMP_RNDN);
0659    }
0660    template <unsigned digits10>
0661    mpc_complex_backend& operator=(gmp_float<digits10> const& val)
0662    {
0663       if (preserve_all_precision() && (mpc_get_prec(data()) != (mpfr_prec_t)mpf_get_prec(val.data())))
0664       {
0665          mpc_complex_backend t(val);
0666          t.swap(*this);
0667       }
0668       else
0669          mpc_set_f(this->m_data, val.data(), GMP_RNDN);
0670       return *this;
0671    }
0672    mpc_complex_backend(mpq_srcptr val) : detail::mpc_complex_imp<0>()
0673    {
0674       mpc_set_q(this->m_data, val, GMP_RNDN);
0675    }
0676    mpc_complex_backend& operator=(mpq_srcptr val)
0677    {
0678       mpc_set_q(this->m_data, val, GMP_RNDN);
0679       return *this;
0680    }
0681    mpc_complex_backend(gmp_rational const& val) : detail::mpc_complex_imp<0>(preserve_all_precision() ? used_gmp_rational_bits(val) : boost::multiprecision::detail::digits10_2_2(thread_default_precision()))
0682    {
0683       mpc_set_q(this->m_data, val.data(), GMP_RNDN);
0684    }
0685    mpc_complex_backend& operator=(gmp_rational const& val)
0686    {
0687       if (this->m_data[0].im->_mpfr_d == nullptr)
0688       {
0689          unsigned requested_precision = this->get_default_precision();
0690          if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
0691          {
0692             unsigned d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(val));
0693             if (d10 > requested_precision)
0694                requested_precision = d10;
0695          }
0696          mpc_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0697       }
0698       else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
0699       {
0700          unsigned requested_precision = this->get_default_precision();
0701          unsigned d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(val));
0702          if (d10 > requested_precision)
0703             this->precision(d10);
0704       }
0705       mpc_set_q(this->m_data, val.data(), GMP_RNDN);
0706       return *this;
0707    }
0708    mpc_complex_backend(mpfr_srcptr val) : detail::mpc_complex_imp<0>(mpfr_get_prec(val))
0709    {
0710       mpc_set_fr(this->m_data, val, GMP_RNDN);
0711    }
0712    mpc_complex_backend& operator=(mpfr_srcptr val)
0713    {
0714       if (mpc_get_prec(data()) != mpfr_get_prec(val))
0715       {
0716          mpc_complex_backend t(val);
0717          t.swap(*this);
0718       }
0719       else
0720          mpc_set_fr(this->m_data, val, GMP_RNDN);
0721       return *this;
0722    }
0723    mpc_complex_backend(const std::complex<float>& val)
0724        : detail::mpc_complex_imp<0>()
0725    {
0726       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0727    }
0728    mpc_complex_backend(const std::complex<double>& val)
0729        : detail::mpc_complex_imp<0>()
0730    {
0731       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0732    }
0733    mpc_complex_backend(const std::complex<long double>& val)
0734        : detail::mpc_complex_imp<0>()
0735    {
0736       mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN);
0737    }
0738    // Construction with precision:
0739    template <class T, class U>
0740    mpc_complex_backend(const T& a, const U& b, unsigned digits10)
0741        : detail::mpc_complex_imp<0>(multiprecision::detail::digits10_2_2(digits10))
0742    {
0743       // We can't use assign_components here because it copies the precision of
0744       // a and b, not digits10....
0745       boost::multiprecision::detail::scoped_precision_options<mpfr_float> scoped(*this);
0746       (void)scoped;
0747       mpfr_float ca(a), cb(b);
0748       mpc_set_fr_fr(this->data(), ca.backend().data(), cb.backend().data(), GMP_RNDN);
0749    }
0750    template <unsigned N>
0751    mpc_complex_backend(const mpfr_float_backend<N>& a, const mpfr_float_backend<N>& b, unsigned digits10)
0752        : detail::mpc_complex_imp<0>(multiprecision::detail::digits10_2_2(digits10))
0753    {
0754       mpc_set_fr_fr(this->data(), a.data(), b.data(), GMP_RNDN);
0755    }
0756 
0757    mpc_complex_backend& operator=(const mpc_complex_backend& o) = default;
0758    // rvalue assign
0759    mpc_complex_backend& operator=(mpc_complex_backend&& o) noexcept = default;
0760 
0761    template <class V>
0762    mpc_complex_backend& operator=(const V& v)
0763    {
0764       constexpr unsigned d10 = std::is_floating_point<V>::value ?
0765          std::numeric_limits<V>::digits10 :
0766          std::numeric_limits<V>::digits10 ? 1 + std::numeric_limits<V>::digits10 :
0767          1 + boost::multiprecision::detail::digits2_2_10(std::numeric_limits<V>::digits);
0768 
0769       if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
0770       {
0771          BOOST_IF_CONSTEXPR(std::is_floating_point<V>::value)
0772          {
0773             if (std::numeric_limits<V>::digits > mpc_get_prec(this->data()))
0774                mpc_set_prec(this->data(), std::numeric_limits<V>::digits);
0775          }
0776       else
0777       {
0778          if (precision() < d10)
0779             this->precision(d10);
0780       }
0781       }
0782 
0783       *static_cast<detail::mpc_complex_imp<0>*>(this) = v;
0784       return *this;
0785    }
0786    mpc_complex_backend& operator=(const mpc_t val)
0787    {
0788       mpc_set_prec(this->m_data, mpc_get_prec(val));
0789       mpc_set(this->m_data, val, GMP_RNDN);
0790       return *this;
0791    }
0792    template <unsigned D>
0793    mpc_complex_backend& operator=(const mpc_complex_backend<D>& val)
0794    {
0795       mpc_set_prec(this->m_data, mpc_get_prec(val.data()));
0796       mpc_set(this->m_data, val.data(), GMP_RNDN);
0797       return *this;
0798    }
0799    template <unsigned D>
0800    mpc_complex_backend& operator=(const mpfr_float_backend<D>& val)
0801    {
0802       if (D == 0 ? this->preserve_component_precision() : this->preserve_related_precision())
0803          mpc_set_prec(this->m_data, mpfr_get_prec(val.data()));
0804       mpc_set_fr(this->m_data, val.data(), GMP_RNDN);
0805       return *this;
0806    }
0807    mpc_complex_backend& operator=(const std::complex<float>& val)
0808    {
0809       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0810       return *this;
0811    }
0812    mpc_complex_backend& operator=(const std::complex<double>& val)
0813    {
0814       mpc_set_d_d(this->m_data, val.real(), val.imag(), GMP_RNDN);
0815       return *this;
0816    }
0817    mpc_complex_backend& operator=(const std::complex<long double>& val)
0818    {
0819       mpc_set_ld_ld(this->m_data, val.real(), val.imag(), GMP_RNDN);
0820       return *this;
0821    }
0822    static unsigned default_precision() noexcept
0823    {
0824       return get_global_default_precision();
0825    }
0826    static void default_precision(unsigned v) noexcept
0827    {
0828       get_global_default_precision() = v;
0829    }
0830    static unsigned thread_default_precision() noexcept
0831    {
0832       return get_default_precision();
0833    }
0834    static void thread_default_precision(unsigned v) noexcept
0835    {
0836       get_default_precision() = v;
0837    }
0838    unsigned precision() const noexcept
0839    {
0840       return multiprecision::detail::digits2_2_10(mpc_get_prec(this->m_data));
0841    }
0842    void precision(unsigned digits10) noexcept
0843    {
0844       mpfr_prec_round(mpc_realref(this->m_data), multiprecision::detail::digits10_2_2((digits10)), GMP_RNDN);
0845       mpfr_prec_round(mpc_imagref(this->m_data), multiprecision::detail::digits10_2_2((digits10)), GMP_RNDN);
0846    }
0847    //
0848    // Variable precision options:
0849    //
0850    static variable_precision_options default_variable_precision_options() noexcept
0851    {
0852       return get_global_default_options();
0853    }
0854    static variable_precision_options thread_default_variable_precision_options() noexcept
0855    {
0856       return get_default_options();
0857    }
0858    static void default_variable_precision_options(variable_precision_options opts)
0859    {
0860       get_global_default_options() = opts;
0861    }
0862    static void thread_default_variable_precision_options(variable_precision_options opts)
0863    {
0864       get_default_options() = opts;
0865    }
0866 };
0867 
0868 template <unsigned digits10, class T>
0869 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_eq(const mpc_complex_backend<digits10>& a, const T& b) noexcept
0870 {
0871    return a.compare(b) == 0;
0872 }
0873 template <unsigned digits10, class T>
0874 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_lt(const mpc_complex_backend<digits10>& a, const T& b) noexcept
0875 {
0876    return a.compare(b) < 0;
0877 }
0878 template <unsigned digits10, class T>
0879 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_gt(const mpc_complex_backend<digits10>& a, const T& b) noexcept
0880 {
0881    return a.compare(b) > 0;
0882 }
0883 
0884 template <unsigned D1, unsigned D2>
0885 inline void eval_add(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o)
0886 {
0887    mpc_add(result.data(), result.data(), o.data(), GMP_RNDN);
0888 }
0889 template <unsigned D1, unsigned D2>
0890 inline void eval_add(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o)
0891 {
0892    mpc_add_fr(result.data(), result.data(), o.data(), GMP_RNDN);
0893 }
0894 template <unsigned D1, unsigned D2>
0895 inline void eval_subtract(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o)
0896 {
0897    mpc_sub(result.data(), result.data(), o.data(), GMP_RNDN);
0898 }
0899 template <unsigned D1, unsigned D2>
0900 inline void eval_subtract(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o)
0901 {
0902    mpc_sub_fr(result.data(), result.data(), o.data(), GMP_RNDN);
0903 }
0904 template <unsigned D1, unsigned D2>
0905 inline void eval_multiply(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o)
0906 {
0907    if ((void*)&result == (void*)&o)
0908       mpc_sqr(result.data(), o.data(), GMP_RNDN);
0909    else
0910       mpc_mul(result.data(), result.data(), o.data(), GMP_RNDN);
0911 }
0912 template <unsigned D1, unsigned D2>
0913 inline void eval_multiply(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o)
0914 {
0915    mpc_mul_fr(result.data(), result.data(), o.data(), GMP_RNDN);
0916 }
0917 template <unsigned D1, unsigned D2>
0918 inline void eval_divide(mpc_complex_backend<D1>& result, const mpc_complex_backend<D2>& o)
0919 {
0920    mpc_div(result.data(), result.data(), o.data(), GMP_RNDN);
0921 }
0922 template <unsigned D1, unsigned D2>
0923 inline void eval_divide(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2>& o)
0924 {
0925    mpc_div_fr(result.data(), result.data(), o.data(), GMP_RNDN);
0926 }
0927 template <unsigned digits10>
0928 inline void eval_add(mpc_complex_backend<digits10>& result, unsigned long i)
0929 {
0930    mpc_add_ui(result.data(), result.data(), i, GMP_RNDN);
0931 }
0932 template <unsigned digits10>
0933 inline void eval_subtract(mpc_complex_backend<digits10>& result, unsigned long i)
0934 {
0935    mpc_sub_ui(result.data(), result.data(), i, GMP_RNDN);
0936 }
0937 template <unsigned digits10>
0938 inline void eval_multiply(mpc_complex_backend<digits10>& result, unsigned long i)
0939 {
0940    mpc_mul_ui(result.data(), result.data(), i, GMP_RNDN);
0941 }
0942 template <unsigned digits10>
0943 inline void eval_divide(mpc_complex_backend<digits10>& result, unsigned long i)
0944 {
0945    mpc_div_ui(result.data(), result.data(), i, GMP_RNDN);
0946 }
0947 template <unsigned digits10>
0948 inline void eval_add(mpc_complex_backend<digits10>& result, long i)
0949 {
0950    if (i > 0)
0951       mpc_add_ui(result.data(), result.data(), i, GMP_RNDN);
0952    else
0953       mpc_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
0954 }
0955 template <unsigned digits10>
0956 inline void eval_subtract(mpc_complex_backend<digits10>& result, long i)
0957 {
0958    if (i > 0)
0959       mpc_sub_ui(result.data(), result.data(), i, GMP_RNDN);
0960    else
0961       mpc_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
0962 }
0963 template <unsigned digits10>
0964 inline void eval_multiply(mpc_complex_backend<digits10>& result, long i)
0965 {
0966    mpc_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
0967    if (i < 0)
0968       mpc_neg(result.data(), result.data(), GMP_RNDN);
0969 }
0970 template <unsigned digits10>
0971 inline void eval_divide(mpc_complex_backend<digits10>& result, long i)
0972 {
0973    mpc_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
0974    if (i < 0)
0975       mpc_neg(result.data(), result.data(), GMP_RNDN);
0976 }
0977 //
0978 // Specialised 3 arg versions of the basic operators:
0979 //
0980 template <unsigned D1, unsigned D2, unsigned D3>
0981 inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y)
0982 {
0983    mpc_add(a.data(), x.data(), y.data(), GMP_RNDN);
0984 }
0985 template <unsigned D1, unsigned D2, unsigned D3>
0986 inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y)
0987 {
0988    mpc_add_fr(a.data(), x.data(), y.data(), GMP_RNDN);
0989 }
0990 template <unsigned D1, unsigned D2, unsigned D3>
0991 inline void eval_add(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y)
0992 {
0993    mpc_add_fr(a.data(), y.data(), x.data(), GMP_RNDN);
0994 }
0995 template <unsigned D1, unsigned D2>
0996 inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y)
0997 {
0998    mpc_add_ui(a.data(), x.data(), y, GMP_RNDN);
0999 }
1000 template <unsigned D1, unsigned D2>
1001 inline void eval_add(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y)
1002 {
1003    if (y < 0)
1004       mpc_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1005    else
1006       mpc_add_ui(a.data(), x.data(), y, GMP_RNDN);
1007 }
1008 template <unsigned D1, unsigned D2>
1009 inline void eval_add(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y)
1010 {
1011    mpc_add_ui(a.data(), y.data(), x, GMP_RNDN);
1012 }
1013 template <unsigned D1, unsigned D2>
1014 inline void eval_add(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y)
1015 {
1016    if (x < 0)
1017    {
1018       mpc_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1019       mpc_neg(a.data(), a.data(), GMP_RNDN);
1020    }
1021    else
1022       mpc_add_ui(a.data(), y.data(), x, GMP_RNDN);
1023 }
1024 template <unsigned D1, unsigned D2, unsigned D3>
1025 inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y)
1026 {
1027    mpc_sub(a.data(), x.data(), y.data(), GMP_RNDN);
1028 }
1029 template <unsigned D1, unsigned D2, unsigned D3>
1030 inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y)
1031 {
1032    mpc_sub_fr(a.data(), x.data(), y.data(), GMP_RNDN);
1033 }
1034 template <unsigned D1, unsigned D2, unsigned D3>
1035 inline void eval_subtract(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y)
1036 {
1037    mpc_fr_sub(a.data(), x.data(), y.data(), GMP_RNDN);
1038 }
1039 template <unsigned D1, unsigned D2>
1040 inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y)
1041 {
1042    mpc_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1043 }
1044 template <unsigned D1, unsigned D2>
1045 inline void eval_subtract(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y)
1046 {
1047    if (y < 0)
1048       mpc_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1049    else
1050       mpc_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1051 }
1052 template <unsigned D1, unsigned D2>
1053 inline void eval_subtract(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y)
1054 {
1055    mpc_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1056 }
1057 template <unsigned D1, unsigned D2>
1058 inline void eval_subtract(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y)
1059 {
1060    if (x < 0)
1061    {
1062       mpc_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1063       mpc_neg(a.data(), a.data(), GMP_RNDN);
1064    }
1065    else
1066       mpc_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1067 }
1068 
1069 template <unsigned D1, unsigned D2, unsigned D3>
1070 inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y)
1071 {
1072    if ((void*)&x == (void*)&y)
1073       mpc_sqr(a.data(), x.data(), GMP_RNDN);
1074    else
1075       mpc_mul(a.data(), x.data(), y.data(), GMP_RNDN);
1076 }
1077 template <unsigned D1, unsigned D2, unsigned D3>
1078 inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y)
1079 {
1080    mpc_mul_fr(a.data(), x.data(), y.data(), GMP_RNDN);
1081 }
1082 template <unsigned D1, unsigned D2, unsigned D3>
1083 inline void eval_multiply(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y)
1084 {
1085    mpc_mul_fr(a.data(), y.data(), x.data(), GMP_RNDN);
1086 }
1087 template <unsigned D1, unsigned D2>
1088 inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y)
1089 {
1090    mpc_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1091 }
1092 template <unsigned D1, unsigned D2>
1093 inline void eval_multiply(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y)
1094 {
1095    if (y < 0)
1096    {
1097       mpc_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1098       a.negate();
1099    }
1100    else
1101       mpc_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1102 }
1103 template <unsigned D1, unsigned D2>
1104 inline void eval_multiply(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y)
1105 {
1106    mpc_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1107 }
1108 template <unsigned D1, unsigned D2>
1109 inline void eval_multiply(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y)
1110 {
1111    if (x < 0)
1112    {
1113       mpc_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1114       mpc_neg(a.data(), a.data(), GMP_RNDN);
1115    }
1116    else
1117       mpc_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1118 }
1119 
1120 template <unsigned D1, unsigned D2, unsigned D3>
1121 inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpc_complex_backend<D3>& y)
1122 {
1123    mpc_div(a.data(), x.data(), y.data(), GMP_RNDN);
1124 }
1125 template <unsigned D1, unsigned D2, unsigned D3>
1126 inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, const mpfr_float_backend<D3>& y)
1127 {
1128    mpc_div_fr(a.data(), x.data(), y.data(), GMP_RNDN);
1129 }
1130 template <unsigned D1, unsigned D2, unsigned D3>
1131 inline void eval_divide(mpc_complex_backend<D1>& a, const mpfr_float_backend<D2>& x, const mpc_complex_backend<D3>& y)
1132 {
1133    mpc_fr_div(a.data(), x.data(), y.data(), GMP_RNDN);
1134 }
1135 template <unsigned D1, unsigned D2>
1136 inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, unsigned long y)
1137 {
1138    mpc_div_ui(a.data(), x.data(), y, GMP_RNDN);
1139 }
1140 template <unsigned D1, unsigned D2>
1141 inline void eval_divide(mpc_complex_backend<D1>& a, const mpc_complex_backend<D2>& x, long y)
1142 {
1143    if (y < 0)
1144    {
1145       mpc_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1146       a.negate();
1147    }
1148    else
1149       mpc_div_ui(a.data(), x.data(), y, GMP_RNDN);
1150 }
1151 template <unsigned D1, unsigned D2>
1152 inline void eval_divide(mpc_complex_backend<D1>& a, unsigned long x, const mpc_complex_backend<D2>& y)
1153 {
1154    mpc_ui_div(a.data(), x, y.data(), GMP_RNDN);
1155 }
1156 template <unsigned D1, unsigned D2>
1157 inline void eval_divide(mpc_complex_backend<D1>& a, long x, const mpc_complex_backend<D2>& y)
1158 {
1159    if (x < 0)
1160    {
1161       mpc_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1162       mpc_neg(a.data(), a.data(), GMP_RNDN);
1163    }
1164    else
1165       mpc_ui_div(a.data(), x, y.data(), GMP_RNDN);
1166 }
1167 
1168 template <unsigned digits10>
1169 inline bool eval_is_zero(const mpc_complex_backend<digits10>& val) noexcept
1170 {
1171    return (0 != mpfr_zero_p(mpc_realref(val.data()))) && (0 != mpfr_zero_p(mpc_imagref(val.data())));
1172 }
1173 template <unsigned digits10>
1174 inline int eval_get_sign(const mpc_complex_backend<digits10>&)
1175 {
1176    static_assert(digits10 == UINT_MAX, "Complex numbers have no sign bit."); // designed to always fail
1177    return 0;
1178 }
1179 
1180 template <unsigned digits10>
1181 inline void eval_convert_to(unsigned long* result, const mpc_complex_backend<digits10>& val)
1182 {
1183    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1184    {
1185       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1186    }
1187    mpfr_float_backend<digits10> t;
1188    mpc_real(t.data(), val.data(), GMP_RNDN);
1189    eval_convert_to(result, t);
1190 }
1191 template <unsigned digits10>
1192 inline void eval_convert_to(long* result, const mpc_complex_backend<digits10>& val)
1193 {
1194    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1195    {
1196       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1197    }
1198    mpfr_float_backend<digits10> t;
1199    mpc_real(t.data(), val.data(), GMP_RNDN);
1200    eval_convert_to(result, t);
1201 }
1202 #ifdef _MPFR_H_HAVE_INTMAX_T
1203 template <unsigned digits10>
1204 inline void eval_convert_to(unsigned long long* result, const mpc_complex_backend<digits10>& val)
1205 {
1206    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1207    {
1208       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1209    }
1210    mpfr_float_backend<digits10> t;
1211    mpc_real(t.data(), val.data(), GMP_RNDN);
1212    eval_convert_to(result, t);
1213 }
1214 template <unsigned digits10>
1215 inline void eval_convert_to(long long* result, const mpc_complex_backend<digits10>& val)
1216 {
1217    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1218    {
1219       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1220    }
1221    mpfr_float_backend<digits10> t;
1222    mpc_real(t.data(), val.data(), GMP_RNDN);
1223    eval_convert_to(result, t);
1224 }
1225 #endif
1226 template <unsigned digits10>
1227 inline void eval_convert_to(double* result, const mpc_complex_backend<digits10>& val) noexcept
1228 {
1229    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1230    {
1231       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1232    }
1233    mpfr_float_backend<digits10> t;
1234    mpc_real(t.data(), val.data(), GMP_RNDN);
1235    eval_convert_to(result, t);
1236 }
1237 template <unsigned digits10>
1238 inline void eval_convert_to(long double* result, const mpc_complex_backend<digits10>& val) noexcept
1239 {
1240    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1241    {
1242       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1243    }
1244    mpfr_float_backend<digits10> t;
1245    mpc_real(t.data(), val.data(), GMP_RNDN);
1246    eval_convert_to(result, t);
1247 }
1248 #ifdef BOOST_HAS_INT128
1249 template <unsigned digits10>
1250 inline void eval_convert_to(uint128_type* result, const mpc_complex_backend<digits10>& val)
1251 {
1252    using default_ops::eval_convert_to;
1253    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1254    {
1255       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1256    }
1257    mpfr_float_backend<digits10> t;
1258    mpc_real(t.data(), val.data(), GMP_RNDN);
1259    eval_convert_to(result, t);
1260 }
1261 template <unsigned digits10>
1262 inline void eval_convert_to(int128_type* result, const mpc_complex_backend<digits10>& val)
1263 {
1264    using default_ops::eval_convert_to;
1265    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1266    {
1267       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1268    }
1269    mpfr_float_backend<digits10> t;
1270    mpc_real(t.data(), val.data(), GMP_RNDN);
1271    eval_convert_to(result, t);
1272 }
1273 #endif
1274 #ifdef BOOST_HAS_FLOAT128
1275 template <unsigned digits10>
1276 inline void eval_convert_to(float128_type* result, const mpc_complex_backend<digits10>& val)
1277 {
1278    using default_ops::eval_convert_to;
1279    if (0 == mpfr_zero_p(mpc_imagref(val.data())))
1280    {
1281       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
1282    }
1283    mpfr_float_backend<digits10> t;
1284    mpc_real(t.data(), val.data(), GMP_RNDN);
1285    eval_convert_to(result, t);
1286 }
1287 #endif
1288 
1289 template <mpfr_allocation_type AllocationType>
1290 inline void assign_components_set_precision(mpc_complex_backend<0>& result, const mpfr_float_backend<0, AllocationType>& a, const mpfr_float_backend<0, AllocationType>& b)
1291 {
1292    if (result.thread_default_variable_precision_options() >= variable_precision_options::preserve_component_precision)
1293    {
1294       unsigned long prec = (std::max)(mpfr_get_prec(a.data()), mpfr_get_prec(b.data()));
1295       mpc_set_prec(result.data(), prec);
1296    }
1297 }
1298 template <unsigned D2, mpfr_allocation_type AllocationType>
1299 inline void assign_components_set_precision(mpc_complex_backend<0>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b)
1300 {
1301    if (result.thread_default_variable_precision_options() >= variable_precision_options::preserve_related_precision)
1302    {
1303       unsigned long prec = (std::max)(mpfr_get_prec(a.data()), mpfr_get_prec(b.data()));
1304       mpc_set_prec(result.data(), prec);
1305    }
1306 }
1307 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1308 inline void assign_components_set_precision(mpc_complex_backend<D1>&, const mpfr_float_backend<D2, AllocationType>&, const mpfr_float_backend<D2, AllocationType>&)
1309 {
1310 }
1311 
1312 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1313 inline void assign_components(mpc_complex_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b)
1314 {
1315    //
1316    // This is called from class number's constructors, so if we have variable
1317    // precision, then copy the precision of the source variables.
1318    //
1319    assign_components_set_precision(result, a, b);
1320    using default_ops::eval_fpclassify;
1321    if (eval_fpclassify(a) == static_cast<int>(FP_NAN))
1322    {
1323       mpc_set_fr(result.data(), a.data(), GMP_RNDN);
1324    }
1325    else if (eval_fpclassify(b) == static_cast<int>(FP_NAN))
1326    {
1327       mpc_set_fr(result.data(), b.data(), GMP_RNDN);
1328    }
1329    else
1330    {
1331       mpc_set_fr_fr(result.data(), a.data(), b.data(), GMP_RNDN);
1332    }
1333 }
1334 
1335 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1336 inline void assign_components(mpc_complex_backend<D1>& result, unsigned long a, unsigned long b)
1337 {
1338    mpc_set_ui_ui(result.data(), a, b, GMP_RNDN);
1339 }
1340 
1341 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1342 inline void assign_components(mpc_complex_backend<D1>& result, long a, long b)
1343 {
1344    mpc_set_si_si(result.data(), a, b, GMP_RNDN);
1345 }
1346 
1347 #if defined(BOOST_HAS_LONG_LONG) && defined(_MPFR_H_HAVE_INTMAX_T)
1348 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1349 inline void assign_components(mpc_complex_backend<D1>& result, unsigned long long a, unsigned long long b)
1350 {
1351    mpc_set_uj_uj(result.data(), a, b, GMP_RNDN);
1352 }
1353 
1354 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1355 inline void assign_components(mpc_complex_backend<D1>& result, long long a, long long b)
1356 {
1357    mpc_set_sj_sj(result.data(), a, b, GMP_RNDN);
1358 }
1359 #endif
1360 
1361 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1362 inline void assign_components(mpc_complex_backend<D1>& result, double a, double b)
1363 {
1364    if (BOOST_MP_ISNAN(a))
1365    {
1366       mpc_set_d(result.data(), a, GMP_RNDN);
1367    }
1368    else if (BOOST_MP_ISNAN(b))
1369    {
1370       mpc_set_d(result.data(), b, GMP_RNDN);
1371    }
1372    else
1373    {
1374       mpc_set_d_d(result.data(), a, b, GMP_RNDN);
1375    }
1376 }
1377 
1378 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1379 inline void assign_components(mpc_complex_backend<D1>& result, long double a, long double b)
1380 {
1381    if (BOOST_MP_ISNAN(a))
1382    {
1383       mpc_set_d(result.data(), a, GMP_RNDN);
1384    }
1385    else if (BOOST_MP_ISNAN(b))
1386    {
1387       mpc_set_d(result.data(), b, GMP_RNDN);
1388    }
1389    else
1390    {
1391       mpc_set_ld_ld(result.data(), a, b, GMP_RNDN);
1392    }
1393 }
1394 
1395 //
1396 // Native non-member operations:
1397 //
1398 template <unsigned Digits10>
1399 inline void eval_sqrt(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& val)
1400 {
1401    mpc_sqrt(result.data(), val.data(), GMP_RNDN);
1402 }
1403 
1404 template <unsigned Digits10>
1405 inline void eval_pow(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& b, const mpc_complex_backend<Digits10>& e)
1406 {
1407    mpc_pow(result.data(), b.data(), e.data(), GMP_RNDN);
1408 }
1409 
1410 template <unsigned Digits10>
1411 inline void eval_exp(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1412 {
1413    mpc_exp(result.data(), arg.data(), GMP_RNDN);
1414 }
1415 
1416 template <unsigned Digits10>
1417 inline void eval_log(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1418 {
1419    mpc_log(result.data(), arg.data(), GMP_RNDN);
1420 }
1421 
1422 template <unsigned Digits10>
1423 inline void eval_log10(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1424 {
1425    mpc_log10(result.data(), arg.data(), GMP_RNDN);
1426 }
1427 
1428 template <unsigned Digits10>
1429 inline void eval_sin(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1430 {
1431    mpc_sin(result.data(), arg.data(), GMP_RNDN);
1432 }
1433 
1434 template <unsigned Digits10>
1435 inline void eval_cos(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1436 {
1437    mpc_cos(result.data(), arg.data(), GMP_RNDN);
1438 }
1439 
1440 template <unsigned Digits10>
1441 inline void eval_tan(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1442 {
1443    mpc_tan(result.data(), arg.data(), GMP_RNDN);
1444 }
1445 
1446 template <unsigned Digits10>
1447 inline void eval_asin(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1448 {
1449    mpc_asin(result.data(), arg.data(), GMP_RNDN);
1450 }
1451 
1452 template <unsigned Digits10>
1453 inline void eval_acos(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1454 {
1455    mpc_acos(result.data(), arg.data(), GMP_RNDN);
1456 }
1457 
1458 template <unsigned Digits10>
1459 inline void eval_atan(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1460 {
1461    mpc_atan(result.data(), arg.data(), GMP_RNDN);
1462 }
1463 
1464 template <unsigned Digits10>
1465 inline void eval_sinh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1466 {
1467    mpc_sinh(result.data(), arg.data(), GMP_RNDN);
1468 }
1469 
1470 template <unsigned Digits10>
1471 inline void eval_cosh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1472 {
1473    mpc_cosh(result.data(), arg.data(), GMP_RNDN);
1474 }
1475 
1476 template <unsigned Digits10>
1477 inline void eval_tanh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1478 {
1479    mpc_tanh(result.data(), arg.data(), GMP_RNDN);
1480 }
1481 
1482 template <unsigned Digits10>
1483 inline void eval_asinh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1484 {
1485    mpc_asinh(result.data(), arg.data(), GMP_RNDN);
1486 }
1487 
1488 template <unsigned Digits10>
1489 inline void eval_acosh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1490 {
1491    mpc_acosh(result.data(), arg.data(), GMP_RNDN);
1492 }
1493 
1494 template <unsigned Digits10>
1495 inline void eval_atanh(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1496 {
1497    mpc_atanh(result.data(), arg.data(), GMP_RNDN);
1498 }
1499 
1500 template <unsigned Digits10>
1501 inline void eval_conj(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1502 {
1503    mpc_conj(result.data(), arg.data(), GMP_RNDN);
1504 }
1505 
1506 template <unsigned Digits10>
1507 inline void eval_proj(mpc_complex_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1508 {
1509    mpc_proj(result.data(), arg.data(), GMP_RNDN);
1510 }
1511 
1512 template <unsigned Digits10>
1513 inline void eval_real(mpfr_float_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1514 {
1515    mpfr_set_prec(result.data(), mpfr_get_prec(mpc_realref(arg.data())));
1516    mpfr_set(result.data(), mpc_realref(arg.data()), GMP_RNDN);
1517 }
1518 template <unsigned Digits10>
1519 inline void eval_imag(mpfr_float_backend<Digits10>& result, const mpc_complex_backend<Digits10>& arg)
1520 {
1521    mpfr_set_prec(result.data(), mpfr_get_prec(mpc_imagref(arg.data())));
1522    mpfr_set(result.data(), mpc_imagref(arg.data()), GMP_RNDN);
1523 }
1524 
1525 template <unsigned Digits10>
1526 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const mpfr_float_backend<Digits10>& arg)
1527 {
1528    mpfr_set(mpc_imagref(result.data()), arg.data(), GMP_RNDN);
1529 }
1530 
1531 template <unsigned Digits10>
1532 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const mpfr_float_backend<Digits10>& arg)
1533 {
1534    mpfr_set(mpc_realref(result.data()), arg.data(), GMP_RNDN);
1535 }
1536 template <unsigned Digits10>
1537 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const gmp_int& arg)
1538 {
1539    mpfr_set_z(mpc_realref(result.data()), arg.data(), GMP_RNDN);
1540 }
1541 template <unsigned Digits10>
1542 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const gmp_rational& arg)
1543 {
1544    mpfr_set_q(mpc_realref(result.data()), arg.data(), GMP_RNDN);
1545 }
1546 template <unsigned Digits10>
1547 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const unsigned& arg)
1548 {
1549    mpfr_set_ui(mpc_realref(result.data()), arg, GMP_RNDN);
1550 }
1551 template <unsigned Digits10>
1552 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const unsigned long& arg)
1553 {
1554    mpfr_set_ui(mpc_realref(result.data()), arg, GMP_RNDN);
1555 }
1556 template <unsigned Digits10>
1557 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const int& arg)
1558 {
1559    mpfr_set_si(mpc_realref(result.data()), arg, GMP_RNDN);
1560 }
1561 template <unsigned Digits10>
1562 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const long& arg)
1563 {
1564    mpfr_set_si(mpc_realref(result.data()), arg, GMP_RNDN);
1565 }
1566 template <unsigned Digits10>
1567 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const float& arg)
1568 {
1569    mpfr_set_flt(mpc_realref(result.data()), arg, GMP_RNDN);
1570 }
1571 template <unsigned Digits10>
1572 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const double& arg)
1573 {
1574    mpfr_set_d(mpc_realref(result.data()), arg, GMP_RNDN);
1575 }
1576 template <unsigned Digits10>
1577 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const long double& arg)
1578 {
1579    mpfr_set_ld(mpc_realref(result.data()), arg, GMP_RNDN);
1580 }
1581 #if defined(BOOST_HAS_LONG_LONG) && defined(_MPFR_H_HAVE_INTMAX_T)
1582 template <unsigned Digits10>
1583 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const unsigned long long& arg)
1584 {
1585    mpfr_set_uj(mpc_realref(result.data()), arg, GMP_RNDN);
1586 }
1587 template <unsigned Digits10>
1588 inline void eval_set_real(mpc_complex_backend<Digits10>& result, const long long& arg)
1589 {
1590    mpfr_set_sj(mpc_realref(result.data()), arg, GMP_RNDN);
1591 }
1592 #endif
1593 
1594 template <unsigned Digits10>
1595 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const gmp_int& arg)
1596 {
1597    mpfr_set_z(mpc_imagref(result.data()), arg.data(), GMP_RNDN);
1598 }
1599 template <unsigned Digits10>
1600 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const gmp_rational& arg)
1601 {
1602    mpfr_set_q(mpc_imagref(result.data()), arg.data(), GMP_RNDN);
1603 }
1604 template <unsigned Digits10>
1605 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const unsigned& arg)
1606 {
1607    mpfr_set_ui(mpc_imagref(result.data()), arg, GMP_RNDN);
1608 }
1609 template <unsigned Digits10>
1610 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const unsigned long& arg)
1611 {
1612    mpfr_set_ui(mpc_imagref(result.data()), arg, GMP_RNDN);
1613 }
1614 template <unsigned Digits10>
1615 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const int& arg)
1616 {
1617    mpfr_set_si(mpc_imagref(result.data()), arg, GMP_RNDN);
1618 }
1619 template <unsigned Digits10>
1620 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const long& arg)
1621 {
1622    mpfr_set_si(mpc_imagref(result.data()), arg, GMP_RNDN);
1623 }
1624 template <unsigned Digits10>
1625 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const float& arg)
1626 {
1627    mpfr_set_flt(mpc_imagref(result.data()), arg, GMP_RNDN);
1628 }
1629 template <unsigned Digits10>
1630 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const double& arg)
1631 {
1632    mpfr_set_d(mpc_imagref(result.data()), arg, GMP_RNDN);
1633 }
1634 template <unsigned Digits10>
1635 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const long double& arg)
1636 {
1637    mpfr_set_ld(mpc_imagref(result.data()), arg, GMP_RNDN);
1638 }
1639 #if defined(BOOST_HAS_LONG_LONG) && defined(_MPFR_H_HAVE_INTMAX_T)
1640 template <unsigned Digits10>
1641 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const unsigned long long& arg)
1642 {
1643    mpfr_set_uj(mpc_imagref(result.data()), arg, GMP_RNDN);
1644 }
1645 template <unsigned Digits10>
1646 inline void eval_set_imag(mpc_complex_backend<Digits10>& result, const long long& arg)
1647 {
1648    mpfr_set_sj(mpc_imagref(result.data()), arg, GMP_RNDN);
1649 }
1650 #endif
1651 
1652 template <unsigned Digits10>
1653 inline std::size_t hash_value(const mpc_complex_backend<Digits10>& val)
1654 {
1655    std::size_t result = 0;
1656    std::size_t len    = val.data()[0].re[0]._mpfr_prec / mp_bits_per_limb;
1657    if (val.data()[0].re[0]._mpfr_prec % mp_bits_per_limb)
1658       ++len;
1659    for (std::size_t i = 0; i < len; ++i)
1660       boost::multiprecision::detail::hash_combine(result, val.data()[0].re[0]._mpfr_d[i]);
1661    boost::multiprecision::detail::hash_combine(result, val.data()[0].re[0]._mpfr_exp, val.data()[0].re[0]._mpfr_sign);
1662 
1663    len = val.data()[0].im[0]._mpfr_prec / mp_bits_per_limb;
1664    if (val.data()[0].im[0]._mpfr_prec % mp_bits_per_limb)
1665       ++len;
1666    for (std::size_t i = 0; i < len; ++i)
1667       boost::multiprecision::detail::hash_combine(result, val.data()[0].im[0]._mpfr_d[i]);
1668    boost::multiprecision::detail::hash_combine(result, val.data()[0].im[0]._mpfr_exp, val.data()[0].im[0]._mpfr_sign);
1669    return result;
1670 }
1671 
1672 } // namespace backends
1673 
1674 namespace detail {
1675 template <>
1676 struct is_variable_precision<backends::mpc_complex_backend<0> > : public std::integral_constant<bool, true>
1677 {};
1678 } // namespace detail
1679 
1680 template <>
1681 struct number_category<detail::canonical<mpc_t, backends::mpc_complex_backend<0> >::type> : public std::integral_constant<int, number_kind_floating_point>
1682 {};
1683 
1684 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1685 struct component_type<number<mpc_complex_backend<Digits10>, ExpressionTemplates> >
1686 {
1687    using type = number<mpfr_float_backend<Digits10>, ExpressionTemplates>;
1688 };
1689 
1690 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1691 struct component_type<number<backends::logged_adaptor<mpc_complex_backend<Digits10> >, ExpressionTemplates> >
1692 {
1693    using type = number<mpfr_float_backend<Digits10>, ExpressionTemplates>;
1694 };
1695 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1696 struct component_type<number<backends::debug_adaptor<mpc_complex_backend<Digits10> >, ExpressionTemplates> >
1697 {
1698    using type = number<backends::debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates>;
1699 };
1700 
1701 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1702 struct complex_result_from_scalar<number<mpfr_float_backend<Digits10>, ExpressionTemplates> >
1703 {
1704    using type = number<mpc_complex_backend<Digits10>, ExpressionTemplates>;
1705 };
1706 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1707 struct complex_result_from_scalar<number<backends::logged_adaptor<mpfr_float_backend<Digits10>>, ExpressionTemplates> >
1708 {
1709    using type = number<mpc_complex_backend<Digits10>, ExpressionTemplates>;
1710 };
1711 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1712 struct complex_result_from_scalar<number<backends::debug_adaptor<mpfr_float_backend<Digits10>>, ExpressionTemplates> >
1713 {
1714    using type = number<backends::debug_adaptor<mpc_complex_backend<Digits10> >, ExpressionTemplates>;
1715 };
1716 
1717 }
1718 
1719 } // namespace boost::multiprecision
1720 
1721 #endif