Back to home page

EIC code displayed by LXR

 
 

    


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

0001 ///////////////////////////////////////////////////////////////////////////////
0002 //  Copyright 2011 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_GENERIC_INTERCONVERT_HPP
0007 #define BOOST_MP_GENERIC_INTERCONVERT_HPP
0008 
0009 #include <cmath>
0010 #include <limits>
0011 #include <boost/multiprecision/detail/standalone_config.hpp>
0012 #include <boost/multiprecision/detail/default_ops.hpp>
0013 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0014 #include <boost/multiprecision/detail/assert.hpp>
0015 #include <boost/multiprecision/detail/functions/trunc.hpp>
0016 
0017 #ifdef BOOST_MSVC
0018 #pragma warning(push)
0019 #pragma warning(disable : 4127 6326)
0020 #endif
0021 
0022 namespace boost { namespace multiprecision { namespace detail {
0023 
0024 template <class To, class From>
0025 inline To do_cast(const From& from)
0026 {
0027    return static_cast<To>(from);
0028 }
0029 template <class To, class B, ::boost::multiprecision::expression_template_option et>
0030 inline To do_cast(const number<B, et>& from)
0031 {
0032    return from.template convert_to<To>();
0033 }
0034 
0035 template <class To, class From>
0036 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
0037 {
0038    using default_ops::eval_add;
0039    using default_ops::eval_bitwise_and;
0040    using default_ops::eval_convert_to;
0041    using default_ops::eval_get_sign;
0042    using default_ops::eval_is_zero;
0043    using default_ops::eval_ldexp;
0044    using default_ops::eval_right_shift;
0045    // smallest unsigned type handled natively by "From" is likely to be it's limb_type:
0046    using l_limb_type = typename canonical<unsigned char, From>::type;
0047    // get the corresponding type that we can assign to "To":
0048    using to_type = typename canonical<l_limb_type, To>::type;
0049    From                                              t(from);
0050    bool                                              is_neg = eval_get_sign(t) < 0;
0051    if (is_neg)
0052       t.negate();
0053    // Pick off the first limb:
0054    l_limb_type limb;
0055    l_limb_type mask = static_cast<l_limb_type>(~static_cast<l_limb_type>(0));
0056    From        fl;
0057    eval_bitwise_and(fl, t, mask);
0058    eval_convert_to(&limb, fl);
0059    to = static_cast<to_type>(limb);
0060    eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
0061    //
0062    // Then keep picking off more limbs until "t" is zero:
0063    //
0064    To       l;
0065    unsigned shift = std::numeric_limits<l_limb_type>::digits;
0066    while (!eval_is_zero(t))
0067    {
0068       eval_bitwise_and(fl, t, mask);
0069       eval_convert_to(&limb, fl);
0070       l = static_cast<to_type>(limb);
0071       eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
0072       eval_ldexp(l, l, shift);
0073       eval_add(to, l);
0074       shift += std::numeric_limits<l_limb_type>::digits;
0075    }
0076    //
0077    // Finish off by setting the sign:
0078    //
0079    if (is_neg)
0080       to.negate();
0081 }
0082 
0083 template <class To, class From>
0084 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
0085 {
0086    using default_ops::eval_bitwise_and;
0087    using default_ops::eval_bitwise_or;
0088    using default_ops::eval_convert_to;
0089    using default_ops::eval_get_sign;
0090    using default_ops::eval_is_zero;
0091    using default_ops::eval_left_shift;
0092    using default_ops::eval_right_shift;
0093    // smallest unsigned type handled natively by "From" is likely to be it's limb_type:
0094    using limb_type = typename canonical<unsigned char, From>::type;
0095    // get the corresponding type that we can assign to "To":
0096    using to_type = typename canonical<limb_type, To>::type;
0097    From                                            t(from);
0098    bool                                            is_neg = eval_get_sign(t) < 0;
0099    if (is_neg)
0100       t.negate();
0101    // Pick off the first limb:
0102    limb_type limb;
0103    limb_type mask = static_cast<limb_type>(~static_cast<limb_type>(0));
0104    From      fl;
0105    eval_bitwise_and(fl, t, mask);
0106    eval_convert_to(&limb, fl);
0107    to = static_cast<to_type>(limb);
0108    eval_right_shift(t, std::numeric_limits<limb_type>::digits);
0109    //
0110    // Then keep picking off more limbs until "t" is zero:
0111    //
0112    To       l;
0113    unsigned shift = std::numeric_limits<limb_type>::digits;
0114    while (!eval_is_zero(t))
0115    {
0116       eval_bitwise_and(fl, t, mask);
0117       eval_convert_to(&limb, fl);
0118       l = static_cast<to_type>(limb);
0119       eval_right_shift(t, std::numeric_limits<limb_type>::digits);
0120       eval_left_shift(l, shift);
0121       eval_bitwise_or(to, l);
0122       shift += std::numeric_limits<limb_type>::digits;
0123    }
0124    //
0125    // Finish off by setting the sign:
0126    //
0127    if (is_neg)
0128       to.negate();
0129 }
0130 
0131 template <class To, class From>
0132 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
0133 {
0134 #ifdef BOOST_MSVC
0135 #pragma warning(push)
0136 //#pragma warning(disable : 4127)
0137 #endif
0138    //
0139    // The code here only works when the radix of "From" is 2, we could try shifting by other
0140    // radixes but it would complicate things.... use a string conversion when the radix is other
0141    // than 2:
0142    //
0143    BOOST_IF_CONSTEXPR(std::numeric_limits<number<From> >::radix != 2)
0144    {
0145       to = from.str(0, std::ios_base::fmtflags()).c_str();
0146       return;
0147    }
0148    else
0149    {
0150       using ui_type = typename canonical<unsigned char, To>::type;
0151 
0152       using default_ops::eval_add;
0153       using default_ops::eval_convert_to;
0154       using default_ops::eval_fpclassify;
0155       using default_ops::eval_get_sign;
0156       using default_ops::eval_is_zero;
0157       using default_ops::eval_subtract;
0158 
0159       //
0160       // First classify the input, then handle the special cases:
0161       //
0162       int c = eval_fpclassify(from);
0163 
0164       if (c == static_cast<int>(FP_ZERO))
0165       {
0166          to = ui_type(0);
0167          return;
0168       }
0169       else if (c == static_cast<int>(FP_NAN))
0170       {
0171          to = static_cast<const char*>("nan");
0172          return;
0173       }
0174       else if (c == static_cast<int>(FP_INFINITE))
0175       {
0176          to = static_cast<const char*>("inf");
0177          if (eval_get_sign(from) < 0)
0178             to.negate();
0179          return;
0180       }
0181 
0182       typename From::exponent_type e;
0183       From                         f, term;
0184       to = ui_type(0);
0185 
0186       eval_frexp(f, from, &e);
0187 
0188       constexpr int shift = std::numeric_limits<std::intmax_t>::digits - 1;
0189 
0190       while (!eval_is_zero(f))
0191       {
0192          // extract int sized bits from f:
0193          eval_ldexp(f, f, shift);
0194          eval_floor(term, f);
0195          e -= shift;
0196          eval_ldexp(to, to, shift);
0197          typename boost::multiprecision::detail::canonical<std::intmax_t, To>::type ll;
0198          eval_convert_to(&ll, term);
0199          eval_add(to, ll);
0200          eval_subtract(f, term);
0201       }
0202       using to_exponent = typename To::exponent_type;
0203       if (e > (std::numeric_limits<to_exponent>::max)())
0204       {
0205          to = static_cast<const char*>("inf");
0206          if (eval_get_sign(from) < 0)
0207             to.negate();
0208          return;
0209       }
0210       if (e < (std::numeric_limits<to_exponent>::min)())
0211       {
0212          to = ui_type(0);
0213          if (eval_get_sign(from) < 0)
0214             to.negate();
0215          return;
0216       }
0217       eval_ldexp(to, to, static_cast<to_exponent>(e));
0218    }
0219 #ifdef BOOST_MSVC
0220 #pragma warning(pop)
0221 #endif
0222 }
0223 
0224 template <class To, class From>
0225 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
0226 {
0227    using to_component_type = typename component_type<number<To> >::type;
0228 
0229    number<From>      t(from);
0230    to_component_type n(numerator(t)), d(denominator(t));
0231    using default_ops::assign_components;
0232    assign_components(to, n.backend(), d.backend());
0233 }
0234 
0235 template <class To, class From>
0236 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
0237 {
0238    using to_component_type = typename component_type<number<To> >::type;
0239 
0240    number<From>      t(from);
0241    to_component_type n(t), d(1);
0242    using default_ops::assign_components;
0243    assign_components(to, n.backend(), d.backend());
0244 }
0245 
0246 template <class LargeInteger>
0247 inline typename std::enable_if<is_signed_number<LargeInteger>::value>::type make_positive(LargeInteger& val)
0248 {
0249    if (val.sign() < 0)
0250       val = -val;
0251 }
0252 template <class LargeInteger>
0253 inline typename std::enable_if<!is_signed_number<LargeInteger>::value>::type make_positive(LargeInteger&){}
0254 
0255 template <class R, class LargeInteger>
0256 R safe_convert_to_float(const LargeInteger& i)
0257 {
0258    if (!i)
0259       return R(0);
0260    BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::max_exponent)
0261    {
0262       using std::ldexp;
0263 
0264       LargeInteger val(i);
0265       make_positive(val);
0266       std::size_t mb = msb(val);
0267       if (mb >= std::numeric_limits<R>::max_exponent)
0268       {
0269          int scale_factor = static_cast<int>(mb) + 1 - std::numeric_limits<R>::max_exponent;
0270          BOOST_MP_ASSERT(scale_factor >= 1);
0271          val >>= scale_factor;
0272          R result = val.template convert_to<R>();
0273          BOOST_IF_CONSTEXPR(std::numeric_limits<R>::digits == 0 || std::numeric_limits<R>::digits >= std::numeric_limits<R>::max_exponent)
0274          {
0275             //
0276             // Calculate and add on the remainder, only if there are more
0277             // digits in the mantissa that the size of the exponent, in
0278             // other words if we are dropping digits in the conversion
0279             // otherwise:
0280             //
0281             LargeInteger remainder(i);
0282             remainder &= (LargeInteger(1) << scale_factor) - 1;
0283             result += ldexp(safe_convert_to_float<R>(remainder), -scale_factor);
0284          }
0285          return i.sign() < 0 ? static_cast<R>(-result) : result;
0286       }
0287    }
0288    return i.template convert_to<R>();
0289 }
0290 
0291 template <class To, class Integer>
0292 inline typename std::enable_if<!(is_number<To>::value || std::is_floating_point<To>::value)>::type
0293 generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const std::integral_constant<bool, true>&)
0294 {
0295    //
0296    // If we get here, then there's something about one type or the other
0297    // that prevents an exactly rounded result from being calculated
0298    // (or at least it's not clear how to implement such a thing).
0299    //
0300    using default_ops::eval_divide;
0301    number<To> fn(safe_convert_to_float<number<To> >(n)), fd(safe_convert_to_float<number<To> >(d));
0302    eval_divide(result, fn.backend(), fd.backend());
0303 }
0304 template <class To, class Integer>
0305 inline typename std::enable_if<is_number<To>::value || std::is_floating_point<To>::value>::type
0306 generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const std::integral_constant<bool, true>&)
0307 {
0308    //
0309    // If we get here, then there's something about one type or the other
0310    // that prevents an exactly rounded result from being calculated
0311    // (or at least it's not clear how to implement such a thing).
0312    //
0313    To fd(safe_convert_to_float<To>(d));
0314    result = safe_convert_to_float<To>(n);
0315    result /= fd;
0316 }
0317 
0318 template <class To, class Integer>
0319 typename std::enable_if<is_number<To>::value || std::is_floating_point<To>::value>::type
0320 generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const std::integral_constant<bool, false>&)
0321 {
0322    //
0323    // If we get here, then the precision of type To is known, and the integer type is unbounded
0324    // so we can use integer division plus manipulation of the remainder to get an exactly
0325    // rounded result.
0326    //
0327    if (num == 0)
0328    {
0329       result = 0;
0330       return;
0331    }
0332    bool s = false;
0333    if (num < 0)
0334    {
0335       s   = true;
0336       num = -num;
0337    }
0338    std::ptrdiff_t denom_bits = msb(denom);
0339    std::ptrdiff_t shift      = std::numeric_limits<To>::digits + denom_bits - msb(num);
0340    if (shift > 0)
0341       num <<= shift;
0342    else if (shift < 0)
0343       denom <<= boost::multiprecision::detail::unsigned_abs(shift);
0344    Integer q, r;
0345    divide_qr(num, denom, q, r);
0346    std::ptrdiff_t q_bits = msb(q);
0347    if (q_bits == std::numeric_limits<To>::digits - 1)
0348    {
0349       //
0350       // Round up if 2 * r > denom:
0351       //
0352       r <<= 1;
0353       int c = r.compare(denom);
0354       if (c > 0)
0355          ++q;
0356       else if ((c == 0) && (q & 1u))
0357       {
0358          ++q;
0359       }
0360    }
0361    else
0362    {
0363       BOOST_MP_ASSERT(q_bits == std::numeric_limits<To>::digits);
0364       //
0365       // We basically already have the rounding info:
0366       //
0367       if (q & 1u)
0368       {
0369          if (r || (q & 2u))
0370             ++q;
0371       }
0372    }
0373    using std::ldexp;
0374    result = do_cast<To>(q);
0375    result = ldexp(result, static_cast<int>(-shift));
0376    if (s)
0377       result = -result;
0378 }
0379 template <class To, class Integer>
0380 inline typename std::enable_if<!(is_number<To>::value || std::is_floating_point<To>::value)>::type
0381 generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const std::integral_constant<bool, false>& tag)
0382 {
0383    number<To> t;
0384    generic_convert_rational_to_float_imp(t, num, denom, tag);
0385    result = t.backend();
0386 }
0387 
0388 template <class To, class From>
0389 inline void generic_convert_rational_to_float(To& result, const From& f)
0390 {
0391    //
0392    // Type From is always a Backend to number<>, or an
0393    // instance of number<>, but we allow
0394    // To to be either a Backend type, or a real number type,
0395    // that way we can call this from generic conversions, and
0396    // from specific conversions to built in types.
0397    //
0398    using actual_from_type = typename std::conditional<is_number<From>::value, From, number<From> >::type                                                                                                                                                                                                           ;
0399    using actual_to_type = typename std::conditional<is_number<To>::value || std::is_floating_point<To>::value, To, number<To> >::type                                                                                                                                                                            ;
0400    using integer_type = typename component_type<actual_from_type>::type                                                                                                                                                                                                                                 ;
0401    using dispatch_tag = std::integral_constant<bool, !std::numeric_limits<integer_type>::is_specialized || std::numeric_limits<integer_type>::is_bounded || !std::numeric_limits<actual_to_type>::is_specialized || !std::numeric_limits<actual_to_type>::is_bounded || (std::numeric_limits<actual_to_type>::radix != 2)>;
0402 
0403    integer_type n(numerator(static_cast<actual_from_type>(f))), d(denominator(static_cast<actual_from_type>(f)));
0404    generic_convert_rational_to_float_imp(result, n, d, dispatch_tag());
0405 }
0406 
0407 template <class To, class From>
0408 inline void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
0409 {
0410    generic_convert_rational_to_float(to, from);
0411 }
0412 
0413 template <class To, class From>
0414 void generic_interconvert_float2rational(To& to, const From& from, const std::integral_constant<int, 2>& /*radix*/)
0415 {
0416    using std::ldexp;
0417    using std::frexp;
0418    using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
0419    constexpr int shift = std::numeric_limits<long long>::digits;
0420    typename From::exponent_type e;
0421    typename component_type<number<To>>::type num, denom;
0422    number<From> val(from);
0423    val = frexp(val, &e);
0424    while (val)
0425    {
0426       val = ldexp(val, shift);
0427       e -= shift;
0428       long long ll = boost::multiprecision::detail::lltrunc(val);
0429       val -= ll;
0430       num <<= shift;
0431       num += ll;
0432    }
0433    denom = ui_type(1u);
0434    if (e < 0)
0435       denom <<= -e;
0436    else if (e > 0)
0437       num <<= e;
0438    assign_components(to, num.backend(), denom.backend());
0439 }
0440 
0441 template <class To, class From, int Radix>
0442 void generic_interconvert_float2rational(To& to, const From& from, const std::integral_constant<int, Radix>& /*radix*/)
0443 {
0444    using std::ilogb;
0445    using std::scalbn;
0446    using std::pow;
0447    using std::abs;
0448    //
0449    // This is almost the same as the binary case above, but we have to use
0450    // scalbn and ilogb rather than ldexp and frexp, we also only extract
0451    // one Radix digit at a time which is terribly inefficient!
0452    //
0453    using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
0454    typename From::exponent_type e;
0455    typename component_type<number<To>>::type num, denom;
0456    number<From> val(from);
0457 
0458    if (!val)
0459    {
0460       to = ui_type(0u);
0461       return;
0462    }
0463 
0464    e   = ilogb(val);
0465    val = scalbn(val, -e);
0466    while (val)
0467    {
0468       long long ll = boost::multiprecision::detail::lltrunc(val);
0469       val -= ll;
0470       val = scalbn(val, 1);
0471       num *= Radix;
0472       num += ll;
0473       --e;
0474    }
0475    ++e;
0476    denom = ui_type(Radix);
0477    denom = pow(denom, abs(e));
0478    if (e > 0)
0479    {
0480       num *= denom;
0481       denom = 1;
0482    }
0483    assign_components(to, num.backend(), denom.backend());
0484 }
0485 
0486 template <class To, class From>
0487 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
0488 {
0489    generic_interconvert_float2rational(to, from, std::integral_constant<int, std::numeric_limits<number<From> >::is_specialized ? std::numeric_limits<number<From> >::radix : 2>());
0490 }
0491 
0492 template <class To, class From>
0493 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
0494 {
0495    number<From> t(from);
0496    number<To>   result(numerator(t) / denominator(t));
0497    to = result.backend();
0498 }
0499 
0500 template <class To, class From>
0501 void generic_interconvert_float2int(To& to, const From& from, const std::integral_constant<int, 2>& /*radix*/)
0502 {
0503    using std::frexp;
0504    using std::ldexp;
0505    
0506    using exponent_type = typename From::exponent_type;
0507    constexpr exponent_type              shift = std::numeric_limits<long long>::digits;
0508    exponent_type                        e;
0509    number<To>                           num(0u);
0510    number<From>                         val(from);
0511    val      = frexp(val, &e);
0512    bool neg = false;
0513    if (val.sign() < 0)
0514    {
0515       val.backend().negate();
0516       neg = true;
0517    }
0518    while (e > 0)
0519    {
0520       exponent_type s = (std::min)(e, shift);
0521       val             = ldexp(val, s);
0522       e -= s;
0523       long long ll = boost::multiprecision::detail::lltrunc(val);
0524       val -= ll;
0525       num <<= s;
0526       num += ll;
0527    }
0528    to = num.backend();
0529    if (neg)
0530       to.negate();
0531 }
0532 
0533 template <class To, class From, int Radix>
0534 void generic_interconvert_float2int(To& to, const From& from, const std::integral_constant<int, Radix>& /*radix*/)
0535 {
0536    using std::ilogb;
0537    using std::scalbn;
0538    //
0539    // This is almost the same as the binary case above, but we have to use
0540    // scalbn and ilogb rather than ldexp and frexp, we also only extract
0541    // one Radix digit at a time which is terribly inefficient!
0542    //
0543    typename From::exponent_type e;
0544    number<To>                   num(0u);
0545    number<From>                 val(from);
0546    e   = ilogb(val);
0547    val = scalbn(val, -e);
0548    while (e >= 0)
0549    {
0550       long long ll = boost::multiprecision::detail::lltrunc(val);
0551       val -= ll;
0552       val = scalbn(val, 1);
0553       num *= Radix;
0554       num += ll;
0555       --e;
0556    }
0557    to = num.backend();
0558 }
0559 
0560 template <class To, class From>
0561 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
0562 {
0563    generic_interconvert_float2int(to, from, std::integral_constant<int, (std::numeric_limits<number<From> >::is_specialized ? std::numeric_limits<number<From> >::radix : 2)>());
0564 }
0565 
0566 template <class To, class From, class tag>
0567 void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, true>&, const tag&)
0568 {
0569    // We just want the real part, and "to" is the correct type already:
0570    eval_real(to, from);
0571 
0572    To im;
0573    eval_imag(im, from);
0574    if (!eval_is_zero(im))
0575       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
0576 }
0577 template <class To, class From>
0578 void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
0579 {
0580    using component_number = typename component_type<number<From> >::type;
0581    using component_backend = typename component_number::backend_type     ;
0582    //
0583    // Get the real part and copy-construct the result from it:
0584    //
0585    scoped_precision_options<component_number> scope(from);
0586    component_backend r;
0587    generic_interconvert_complex_to_scalar(r, from, std::integral_constant<bool, true>(), std::integral_constant<bool, true>());
0588    to = r;
0589 }
0590 template <class To, class From>
0591 void generic_interconvert_complex_to_scalar(To& to, const From& from, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&)
0592 {
0593    using component_number = typename component_type<number<From> >::type;
0594    using component_backend = typename component_number::backend_type;
0595    //
0596    // Get the real part and use a generic_interconvert to type To:
0597    //
0598    scoped_precision_options<component_number> scope(from);
0599    component_backend r;
0600    generic_interconvert_complex_to_scalar(r, from, std::integral_constant<bool, true>(), std::integral_constant<bool, true>());
0601    generic_interconvert(to, r, std::integral_constant<int, number_category<To>::value>(), std::integral_constant<int, number_category<component_backend>::value>());
0602 }
0603 
0604 template <class To, class From>
0605 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_complex>& /*from_type*/)
0606 {
0607    using component_number = typename component_type<number<From> >::type;
0608    using component_backend = typename component_number::backend_type     ;
0609 
0610    generic_interconvert_complex_to_scalar(to, from, std::integral_constant<bool, std::is_same<component_backend, To>::value>(), std::integral_constant<bool, std::is_constructible<To, const component_backend&>::value>());
0611 }
0612 template <class To, class From>
0613 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_complex>& /*from_type*/)
0614 {
0615    using component_number = typename component_type<number<From> >::type;
0616    using component_backend = typename component_number::backend_type     ;
0617 
0618    generic_interconvert_complex_to_scalar(to, from, std::integral_constant<bool, std::is_same<component_backend, To>::value>(), std::integral_constant<bool, std::is_constructible<To, const component_backend&>::value>());
0619 }
0620 template <class To, class From>
0621 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_complex>& /*from_type*/)
0622 {
0623    using component_number = typename component_type<number<From> >::type;
0624    using component_backend = typename component_number::backend_type     ;
0625 
0626    generic_interconvert_complex_to_scalar(to, from, std::integral_constant<bool, std::is_same<component_backend, To>::value>(), std::integral_constant<bool, std::is_constructible<To, const component_backend&>::value>());
0627 }
0628 template <class To, class From>
0629 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_complex>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/)
0630 {
0631    using component_number = typename component_type<number<To> >::type;
0632 
0633    scoped_source_precision<number<From> >     scope1;
0634    scoped_precision_options<component_number> scope2(number<To>::thread_default_precision(), number<To>::thread_default_variable_precision_options());
0635    (void)scope1;
0636    (void)scope2;
0637 
0638    number<From>     f(from);
0639    component_number scalar(f);
0640    number<To> result(scalar);
0641    to = result.backend();
0642 }
0643 template <class To, class From>
0644 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_complex>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/)
0645 {
0646    using component_number = typename component_type<number<To> >::type;
0647 
0648    scoped_source_precision<number<From> >     scope1;
0649    scoped_precision_options<component_number> scope2(number<To>::thread_default_precision(), number<To>::thread_default_variable_precision_options());
0650    (void)scope1;
0651    (void)scope2;
0652 
0653    number<From>     f(from);
0654    component_number scalar(f);
0655    number<To> result(scalar);
0656    to = result.backend();
0657 }
0658 template <class To, class From>
0659 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_complex>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/)
0660 {
0661    using component_number = typename component_type<number<To> >::type;
0662 
0663    scoped_source_precision<number<From> > scope1;
0664    scoped_precision_options<component_number> scope2(number<To>::thread_default_precision(), number<To>::thread_default_variable_precision_options());
0665    (void)scope1;
0666    (void)scope2;
0667 
0668    number<From> f(from);
0669    component_number scalar(f);
0670    number<To> result(scalar);
0671    to = result.backend();
0672 }
0673 template <class To, class From, int Tag1, int Tag2>
0674 void generic_interconvert(To& /*to*/, const From& /*from*/, const std::integral_constant<int, Tag1>& /*to_type*/, const std::integral_constant<int, Tag2>& /*from_type*/)
0675 {
0676    static_assert(sizeof(To) == 0, "Sorry, you asked for a conversion bewteen types that hasn't been implemented yet!!");
0677 }
0678 
0679 }
0680 }
0681 } // namespace boost::multiprecision::detail
0682 
0683 #ifdef BOOST_MSVC
0684 #pragma warning(pop)
0685 #endif
0686 
0687 #endif // BOOST_MP_GENERIC_INTERCONVERT_HPP