]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/multiprecision/detail/generic_interconvert.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / multiprecision / detail / generic_interconvert.hpp
CommitLineData
7c673cae
FG
1///////////////////////////////////////////////////////////////////////////////
2// Copyright 2011 John Maddock. Distributed under the Boost
3// Software License, Version 1.0. (See accompanying file
4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef BOOST_MP_GENERIC_INTERCONVERT_HPP
7#define BOOST_MP_GENERIC_INTERCONVERT_HPP
8
9#include <boost/multiprecision/detail/default_ops.hpp>
10
11#ifdef BOOST_MSVC
12#pragma warning(push)
92f5a8d4 13#pragma warning(disable : 4127 6326)
7c673cae
FG
14#endif
15
92f5a8d4 16namespace boost { namespace multiprecision { namespace detail {
7c673cae
FG
17
18template <class To, class From>
92f5a8d4 19inline To do_cast(const From& from)
7c673cae
FG
20{
21 return static_cast<To>(from);
22}
23template <class To, class B, ::boost::multiprecision::expression_template_option et>
24inline To do_cast(const number<B, et>& from)
25{
26 return from.template convert_to<To>();
27}
28
29template <class To, class From>
30void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/)
31{
92f5a8d4 32 using default_ops::eval_add;
7c673cae
FG
33 using default_ops::eval_bitwise_and;
34 using default_ops::eval_convert_to;
92f5a8d4 35 using default_ops::eval_get_sign;
7c673cae 36 using default_ops::eval_is_zero;
92f5a8d4
TL
37 using default_ops::eval_ldexp;
38 using default_ops::eval_right_shift;
7c673cae 39 // smallest unsigned type handled natively by "From" is likely to be it's limb_type:
92f5a8d4 40 typedef typename canonical<unsigned char, From>::type l_limb_type;
7c673cae 41 // get the corresponding type that we can assign to "To":
92f5a8d4
TL
42 typedef typename canonical<l_limb_type, To>::type to_type;
43 From t(from);
44 bool is_neg = eval_get_sign(t) < 0;
45 if (is_neg)
7c673cae
FG
46 t.negate();
47 // Pick off the first limb:
48 l_limb_type limb;
49 l_limb_type mask = static_cast<l_limb_type>(~static_cast<l_limb_type>(0));
92f5a8d4 50 From fl;
7c673cae
FG
51 eval_bitwise_and(fl, t, mask);
52 eval_convert_to(&limb, fl);
53 to = static_cast<to_type>(limb);
54 eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
55 //
56 // Then keep picking off more limbs until "t" is zero:
57 //
92f5a8d4 58 To l;
7c673cae 59 unsigned shift = std::numeric_limits<l_limb_type>::digits;
92f5a8d4 60 while (!eval_is_zero(t))
7c673cae
FG
61 {
62 eval_bitwise_and(fl, t, mask);
63 eval_convert_to(&limb, fl);
64 l = static_cast<to_type>(limb);
65 eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
66 eval_ldexp(l, l, shift);
67 eval_add(to, l);
68 shift += std::numeric_limits<l_limb_type>::digits;
69 }
70 //
71 // Finish off by setting the sign:
72 //
92f5a8d4 73 if (is_neg)
7c673cae
FG
74 to.negate();
75}
76
77template <class To, class From>
78void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/)
79{
7c673cae 80 using default_ops::eval_bitwise_and;
7c673cae 81 using default_ops::eval_bitwise_or;
92f5a8d4
TL
82 using default_ops::eval_convert_to;
83 using default_ops::eval_get_sign;
7c673cae 84 using default_ops::eval_is_zero;
92f5a8d4
TL
85 using default_ops::eval_left_shift;
86 using default_ops::eval_right_shift;
7c673cae 87 // smallest unsigned type handled natively by "From" is likely to be it's limb_type:
92f5a8d4 88 typedef typename canonical<unsigned char, From>::type limb_type;
7c673cae 89 // get the corresponding type that we can assign to "To":
92f5a8d4
TL
90 typedef typename canonical<limb_type, To>::type to_type;
91 From t(from);
92 bool is_neg = eval_get_sign(t) < 0;
93 if (is_neg)
7c673cae
FG
94 t.negate();
95 // Pick off the first limb:
96 limb_type limb;
97 limb_type mask = static_cast<limb_type>(~static_cast<limb_type>(0));
92f5a8d4 98 From fl;
7c673cae
FG
99 eval_bitwise_and(fl, t, mask);
100 eval_convert_to(&limb, fl);
101 to = static_cast<to_type>(limb);
102 eval_right_shift(t, std::numeric_limits<limb_type>::digits);
103 //
104 // Then keep picking off more limbs until "t" is zero:
105 //
92f5a8d4 106 To l;
7c673cae 107 unsigned shift = std::numeric_limits<limb_type>::digits;
92f5a8d4 108 while (!eval_is_zero(t))
7c673cae
FG
109 {
110 eval_bitwise_and(fl, t, mask);
111 eval_convert_to(&limb, fl);
112 l = static_cast<to_type>(limb);
113 eval_right_shift(t, std::numeric_limits<limb_type>::digits);
114 eval_left_shift(l, shift);
115 eval_bitwise_or(to, l);
116 shift += std::numeric_limits<limb_type>::digits;
117 }
118 //
119 // Finish off by setting the sign:
120 //
92f5a8d4 121 if (is_neg)
7c673cae
FG
122 to.negate();
123}
124
125template <class To, class From>
126void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
127{
128#ifdef BOOST_MSVC
129#pragma warning(push)
92f5a8d4 130#pragma warning(disable : 4127)
7c673cae
FG
131#endif
132 //
133 // The code here only works when the radix of "From" is 2, we could try shifting by other
134 // radixes but it would complicate things.... use a string conversion when the radix is other
135 // than 2:
136 //
92f5a8d4 137 if (std::numeric_limits<number<From> >::radix != 2)
7c673cae
FG
138 {
139 to = from.str(0, std::ios_base::fmtflags()).c_str();
140 return;
141 }
142
7c673cae
FG
143 typedef typename canonical<unsigned char, To>::type ui_type;
144
7c673cae 145 using default_ops::eval_add;
7c673cae 146 using default_ops::eval_convert_to;
92f5a8d4 147 using default_ops::eval_fpclassify;
7c673cae
FG
148 using default_ops::eval_get_sign;
149 using default_ops::eval_is_zero;
92f5a8d4 150 using default_ops::eval_subtract;
7c673cae
FG
151
152 //
153 // First classify the input, then handle the special cases:
154 //
155 int c = eval_fpclassify(from);
156
92f5a8d4 157 if (c == (int)FP_ZERO)
7c673cae
FG
158 {
159 to = ui_type(0);
160 return;
161 }
92f5a8d4 162 else if (c == (int)FP_NAN)
7c673cae
FG
163 {
164 to = static_cast<const char*>("nan");
165 return;
166 }
92f5a8d4 167 else if (c == (int)FP_INFINITE)
7c673cae
FG
168 {
169 to = static_cast<const char*>("inf");
92f5a8d4 170 if (eval_get_sign(from) < 0)
7c673cae
FG
171 to.negate();
172 return;
173 }
174
175 typename From::exponent_type e;
92f5a8d4 176 From f, term;
7c673cae
FG
177 to = ui_type(0);
178
179 eval_frexp(f, from, &e);
180
181 static const int shift = std::numeric_limits<boost::intmax_t>::digits - 1;
182
92f5a8d4 183 while (!eval_is_zero(f))
7c673cae
FG
184 {
185 // extract int sized bits from f:
186 eval_ldexp(f, f, shift);
187 eval_floor(term, f);
188 e -= shift;
189 eval_ldexp(to, to, shift);
190 typename boost::multiprecision::detail::canonical<boost::intmax_t, To>::type ll;
191 eval_convert_to(&ll, term);
192 eval_add(to, ll);
193 eval_subtract(f, term);
194 }
195 typedef typename To::exponent_type to_exponent;
92f5a8d4 196 if (e > (std::numeric_limits<to_exponent>::max)())
7c673cae
FG
197 {
198 to = static_cast<const char*>("inf");
92f5a8d4
TL
199 if (eval_get_sign(from) < 0)
200 to.negate();
201 return;
202 }
203 if (e < (std::numeric_limits<to_exponent>::min)())
204 {
205 to = ui_type(0);
206 if (eval_get_sign(from) < 0)
7c673cae
FG
207 to.negate();
208 return;
209 }
210 eval_ldexp(to, to, static_cast<to_exponent>(e));
211#ifdef BOOST_MSVC
212#pragma warning(pop)
213#endif
214}
215
216template <class To, class From>
217void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/)
218{
92f5a8d4 219 typedef typename component_type<number<To> >::type to_component_type;
7c673cae 220
92f5a8d4 221 number<From> t(from);
7c673cae
FG
222 to_component_type n(numerator(t)), d(denominator(t));
223 using default_ops::assign_components;
224 assign_components(to, n.backend(), d.backend());
225}
226
227template <class To, class From>
228void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/)
229{
92f5a8d4 230 typedef typename component_type<number<To> >::type to_component_type;
7c673cae 231
92f5a8d4 232 number<From> t(from);
7c673cae
FG
233 to_component_type n(t), d(1);
234 using default_ops::assign_components;
235 assign_components(to, n.backend(), d.backend());
236}
237
238template <class R, class LargeInteger>
239R safe_convert_to_float(const LargeInteger& i)
240{
241 using std::ldexp;
92f5a8d4 242 if (!i)
7c673cae 243 return R(0);
92f5a8d4 244 if (std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::max_exponent)
7c673cae
FG
245 {
246 LargeInteger val(i);
92f5a8d4 247 if (val.sign() < 0)
7c673cae
FG
248 val = -val;
249 unsigned mb = msb(val);
92f5a8d4 250 if (mb >= std::numeric_limits<R>::max_exponent)
7c673cae
FG
251 {
252 int scale_factor = (int)mb + 1 - std::numeric_limits<R>::max_exponent;
253 BOOST_ASSERT(scale_factor >= 1);
254 val >>= scale_factor;
255 R result = val.template convert_to<R>();
92f5a8d4 256 if (std::numeric_limits<R>::digits == 0 || std::numeric_limits<R>::digits >= std::numeric_limits<R>::max_exponent)
7c673cae
FG
257 {
258 //
259 // Calculate and add on the remainder, only if there are more
92f5a8d4 260 // digits in the mantissa that the size of the exponent, in
7c673cae
FG
261 // other words if we are dropping digits in the conversion
262 // otherwise:
263 //
264 LargeInteger remainder(i);
265 remainder &= (LargeInteger(1) << scale_factor) - 1;
266 result += ldexp(safe_convert_to_float<R>(remainder), -scale_factor);
267 }
268 return i.sign() < 0 ? static_cast<R>(-result) : result;
269 }
270 }
271 return i.template convert_to<R>();
272}
273
274template <class To, class Integer>
92f5a8d4
TL
275inline typename disable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
276generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const mpl::true_&)
7c673cae
FG
277{
278 //
279 // If we get here, then there's something about one type or the other
280 // that prevents an exactly rounded result from being calculated
281 // (or at least it's not clear how to implement such a thing).
282 //
283 using default_ops::eval_divide;
284 number<To> fn(safe_convert_to_float<number<To> >(n)), fd(safe_convert_to_float<number<To> >(d));
285 eval_divide(result, fn.backend(), fd.backend());
286}
287template <class To, class Integer>
92f5a8d4
TL
288inline typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
289generic_convert_rational_to_float_imp(To& result, const Integer& n, const Integer& d, const mpl::true_&)
7c673cae
FG
290{
291 //
292 // If we get here, then there's something about one type or the other
293 // that prevents an exactly rounded result from being calculated
294 // (or at least it's not clear how to implement such a thing).
295 //
296 To fd(safe_convert_to_float<To>(d));
297 result = safe_convert_to_float<To>(n);
298 result /= fd;
299}
300
301template <class To, class Integer>
92f5a8d4
TL
302typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
303generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const mpl::false_&)
7c673cae
FG
304{
305 //
306 // If we get here, then the precision of type To is known, and the integer type is unbounded
307 // so we can use integer division plus manipulation of the remainder to get an exactly
308 // rounded result.
309 //
92f5a8d4 310 if (num == 0)
7c673cae
FG
311 {
312 result = 0;
313 return;
314 }
315 bool s = false;
92f5a8d4 316 if (num < 0)
7c673cae 317 {
92f5a8d4 318 s = true;
7c673cae
FG
319 num = -num;
320 }
321 int denom_bits = msb(denom);
92f5a8d4
TL
322 int shift = std::numeric_limits<To>::digits + denom_bits - msb(num);
323 if (shift > 0)
7c673cae 324 num <<= shift;
92f5a8d4 325 else if (shift < 0)
7c673cae
FG
326 denom <<= boost::multiprecision::detail::unsigned_abs(shift);
327 Integer q, r;
328 divide_qr(num, denom, q, r);
329 int q_bits = msb(q);
92f5a8d4 330 if (q_bits == std::numeric_limits<To>::digits - 1)
7c673cae
FG
331 {
332 //
333 // Round up if 2 * r > denom:
334 //
335 r <<= 1;
336 int c = r.compare(denom);
92f5a8d4 337 if (c > 0)
7c673cae 338 ++q;
92f5a8d4 339 else if ((c == 0) && (q & 1u))
7c673cae
FG
340 {
341 ++q;
342 }
343 }
344 else
345 {
346 BOOST_ASSERT(q_bits == std::numeric_limits<To>::digits);
347 //
348 // We basically already have the rounding info:
349 //
92f5a8d4 350 if (q & 1u)
7c673cae 351 {
92f5a8d4 352 if (r || (q & 2u))
7c673cae
FG
353 ++q;
354 }
355 }
356 using std::ldexp;
357 result = do_cast<To>(q);
358 result = ldexp(result, -shift);
92f5a8d4 359 if (s)
7c673cae
FG
360 result = -result;
361}
362template <class To, class Integer>
363inline typename disable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
92f5a8d4 364generic_convert_rational_to_float_imp(To& result, Integer& num, Integer& denom, const mpl::false_& tag)
7c673cae
FG
365{
366 number<To> t;
367 generic_convert_rational_to_float_imp(t, num, denom, tag);
368 result = t.backend();
369}
370
371template <class To, class From>
372inline void generic_convert_rational_to_float(To& result, const From& f)
373{
374 //
375 // Type From is always a Backend to number<>, or an
376 // instance of number<>, but we allow
377 // To to be either a Backend type, or a real number type,
378 // that way we can call this from generic conversions, and
379 // from specific conversions to built in types.
380 //
92f5a8d4
TL
381 typedef typename mpl::if_c<is_number<From>::value, From, number<From> >::type actual_from_type;
382 typedef typename mpl::if_c<is_number<To>::value || is_floating_point<To>::value, To, number<To> >::type actual_to_type;
383 typedef typename component_type<actual_from_type>::type integer_type;
384 typedef mpl::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)> dispatch_tag;
7c673cae
FG
385
386 integer_type n(numerator(static_cast<actual_from_type>(f))), d(denominator(static_cast<actual_from_type>(f)));
387 generic_convert_rational_to_float_imp(result, n, d, dispatch_tag());
388}
389
390template <class To, class From>
391inline void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/)
392{
393 generic_convert_rational_to_float(to, from);
394}
395
396template <class To, class From>
397void generic_interconvert_float2rational(To& to, const From& from, const mpl::int_<2>& /*radix*/)
398{
399 typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
92f5a8d4
TL
400 static const int shift = std::numeric_limits<boost::long_long_type>::digits;
401 typename From::exponent_type e;
402 typename component_type<number<To> >::type num, denom;
403 number<From> val(from);
7c673cae 404 val = frexp(val, &e);
92f5a8d4 405 while (val)
7c673cae
FG
406 {
407 val = ldexp(val, shift);
408 e -= shift;
409 boost::long_long_type ll = boost::math::lltrunc(val);
410 val -= ll;
411 num <<= shift;
412 num += ll;
413 }
414 denom = ui_type(1u);
92f5a8d4 415 if (e < 0)
7c673cae 416 denom <<= -e;
92f5a8d4 417 else if (e > 0)
7c673cae
FG
418 num <<= e;
419 assign_components(to, num.backend(), denom.backend());
420}
421
422template <class To, class From, int Radix>
423void generic_interconvert_float2rational(To& to, const From& from, const mpl::int_<Radix>& /*radix*/)
424{
425 //
426 // This is almost the same as the binary case above, but we have to use
427 // scalbn and ilogb rather than ldexp and frexp, we also only extract
428 // one Radix digit at a time which is terribly inefficient!
429 //
430 typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
92f5a8d4
TL
431 typename From::exponent_type e;
432 typename component_type<number<To> >::type num, denom;
433 number<From> val(from);
11fdf7f2
TL
434
435 if (!val)
436 {
437 to = ui_type(0u);
438 return;
439 }
440
92f5a8d4 441 e = ilogb(val);
7c673cae 442 val = scalbn(val, -e);
92f5a8d4 443 while (val)
7c673cae
FG
444 {
445 boost::long_long_type ll = boost::math::lltrunc(val);
446 val -= ll;
447 val = scalbn(val, 1);
448 num *= Radix;
449 num += ll;
450 --e;
451 }
452 ++e;
453 denom = ui_type(Radix);
454 denom = pow(denom, abs(e));
92f5a8d4 455 if (e > 0)
7c673cae
FG
456 {
457 num *= denom;
458 denom = 1;
459 }
460 assign_components(to, num.backend(), denom.backend());
461}
462
463template <class To, class From>
464void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
465{
466 generic_interconvert_float2rational(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
467}
468
469template <class To, class From>
470void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/)
471{
472 number<From> t(from);
92f5a8d4 473 number<To> result(numerator(t) / denominator(t));
7c673cae
FG
474 to = result.backend();
475}
476
477template <class To, class From>
478void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<2>& /*radix*/)
479{
480 typedef typename From::exponent_type exponent_type;
92f5a8d4
TL
481 static const exponent_type shift = std::numeric_limits<boost::long_long_type>::digits;
482 exponent_type e;
483 number<To> num(0u);
484 number<From> val(from);
485 val = frexp(val, &e);
486 bool neg = false;
487 if (val.sign() < 0)
488 {
489 val.backend().negate();
490 neg = true;
491 }
492 while (e > 0)
7c673cae 493 {
92f5a8d4
TL
494 exponent_type s = (std::min)(e, shift);
495 val = ldexp(val, s);
7c673cae
FG
496 e -= s;
497 boost::long_long_type ll = boost::math::lltrunc(val);
498 val -= ll;
499 num <<= s;
500 num += ll;
501 }
502 to = num.backend();
92f5a8d4
TL
503 if (neg)
504 to.negate();
7c673cae
FG
505}
506
507template <class To, class From, int Radix>
508void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<Radix>& /*radix*/)
509{
510 //
511 // This is almost the same as the binary case above, but we have to use
512 // scalbn and ilogb rather than ldexp and frexp, we also only extract
513 // one Radix digit at a time which is terribly inefficient!
514 //
515 typename From::exponent_type e;
92f5a8d4
TL
516 number<To> num(0u);
517 number<From> val(from);
518 e = ilogb(val);
7c673cae 519 val = scalbn(val, -e);
92f5a8d4 520 while (e >= 0)
7c673cae
FG
521 {
522 boost::long_long_type ll = boost::math::lltrunc(val);
523 val -= ll;
524 val = scalbn(val, 1);
525 num *= Radix;
526 num += ll;
527 --e;
528 }
529 to = num.backend();
530}
531
532template <class To, class From>
533void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
534{
535 generic_interconvert_float2int(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
536}
537
92f5a8d4
TL
538template <class To, class From, class tag>
539void generic_interconvert_complex_to_scalar(To& to, const From& from, const mpl::true_&, const tag&)
540{
541 // We just want the real part, and "to" is the correct type already:
542 eval_real(to, from);
543
544 To im;
545 eval_imag(im, from);
546 if (!eval_is_zero(im))
547 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
7c673cae 548}
92f5a8d4
TL
549template <class To, class From>
550void generic_interconvert_complex_to_scalar(To& to, const From& from, const mpl::false_&, const mpl::true_&)
551{
552 typedef typename component_type<number<From> >::type component_number;
553 typedef typename component_number::backend_type component_backend;
554 //
555 // Get the real part and copy-construct the result from it:
556 //
557 component_backend r;
558 generic_interconvert_complex_to_scalar(r, from, mpl::true_(), mpl::true_());
559 to = r;
560}
561template <class To, class From>
562void generic_interconvert_complex_to_scalar(To& to, const From& from, const mpl::false_&, const mpl::false_&)
563{
564 typedef typename component_type<number<From> >::type component_number;
565 typedef typename component_number::backend_type component_backend;
566 //
567 // Get the real part and use a generic_interconvert to type To:
568 //
569 component_backend r;
570 generic_interconvert_complex_to_scalar(r, from, mpl::true_(), mpl::true_());
571 generic_interconvert(to, r, mpl::int_<number_category<To>::value>(), mpl::int_<number_category<To>::value>());
572}
573
574template <class To, class From>
575void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_complex>& /*from_type*/)
576{
577 typedef typename component_type<number<From> >::type component_number;
578 typedef typename component_number::backend_type component_backend;
579
580 generic_interconvert_complex_to_scalar(to, from, mpl::bool_<boost::is_same<component_backend, To>::value>(), mpl::bool_<boost::is_constructible<To, const component_backend&>::value>());
581}
582template <class To, class From>
583void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_complex>& /*from_type*/)
584{
585 typedef typename component_type<number<From> >::type component_number;
586 typedef typename component_number::backend_type component_backend;
587
588 generic_interconvert_complex_to_scalar(to, from, mpl::bool_<boost::is_same<component_backend, To>::value>(), mpl::bool_<boost::is_constructible<To, const component_backend&>::value>());
7c673cae 589}
92f5a8d4
TL
590
591}
592}
593} // namespace boost::multiprecision::detail
7c673cae
FG
594
595#ifdef BOOST_MSVC
596#pragma warning(pop)
597#endif
598
92f5a8d4 599#endif // BOOST_MP_GENERIC_INTERCONVERT_HPP