File indexing completed on 2025-01-18 09:42:21
0001
0002
0003
0004
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>& , const std::integral_constant<int, number_kind_integer>& )
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
0046 using l_limb_type = typename canonical<unsigned char, From>::type;
0047
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
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
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
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>& , const std::integral_constant<int, number_kind_integer>& )
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
0094 using limb_type = typename canonical<unsigned char, From>::type;
0095
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
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
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
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>& , const std::integral_constant<int, number_kind_floating_point>& )
0133 {
0134 #ifdef BOOST_MSVC
0135 #pragma warning(push)
0136
0137 #endif
0138
0139
0140
0141
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
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
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>& , const std::integral_constant<int, number_kind_rational>& )
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>& , const std::integral_constant<int, number_kind_integer>& )
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
0277
0278
0279
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
0297
0298
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
0310
0311
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
0324
0325
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
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
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
0393
0394
0395
0396
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>& , const std::integral_constant<int, number_kind_rational>& )
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>& )
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>& )
0443 {
0444 using std::ilogb;
0445 using std::scalbn;
0446 using std::pow;
0447 using std::abs;
0448
0449
0450
0451
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>& , const std::integral_constant<int, number_kind_floating_point>& )
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>& , const std::integral_constant<int, number_kind_rational>& )
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>& )
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>& )
0535 {
0536 using std::ilogb;
0537 using std::scalbn;
0538
0539
0540
0541
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>& , const std::integral_constant<int, number_kind_floating_point>& )
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
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
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
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>& , const std::integral_constant<int, number_kind_complex>& )
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>& , const std::integral_constant<int, number_kind_complex>& )
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>& , const std::integral_constant<int, number_kind_complex>& )
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>& , const std::integral_constant<int, number_kind_integer>& )
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>& , const std::integral_constant<int, number_kind_rational>& )
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>& , const std::integral_constant<int, number_kind_floating_point>& )
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& , const From& , const std::integral_constant<int, Tag1>& , const std::integral_constant<int, Tag2>& )
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 }
0682
0683 #ifdef BOOST_MSVC
0684 #pragma warning(pop)
0685 #endif
0686
0687 #endif