summaryrefslogtreecommitdiff
path: root/boost/multiprecision/detail/generic_interconvert.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision/detail/generic_interconvert.hpp')
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp71
1 files changed, 68 insertions, 3 deletions
diff --git a/boost/multiprecision/detail/generic_interconvert.hpp b/boost/multiprecision/detail/generic_interconvert.hpp
index 6a840f8544..e2d8487c87 100644
--- a/boost/multiprecision/detail/generic_interconvert.hpp
+++ b/boost/multiprecision/detail/generic_interconvert.hpp
@@ -147,6 +147,8 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
using default_ops::eval_add;
using default_ops::eval_subtract;
using default_ops::eval_convert_to;
+ using default_ops::eval_get_sign;
+ using default_ops::eval_is_zero;
//
// First classify the input, then handle the special cases:
@@ -425,7 +427,7 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
//
typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
typename From::exponent_type e;
- typename component_type<To>::type num, denom;
+ typename component_type<number<To> >::type num, denom;
number<From> val(from);
e = ilogb(val);
val = scalbn(val, -e);
@@ -446,7 +448,7 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
num *= denom;
denom = 1;
}
- assign_components(to, num, denom);
+ assign_components(to, num.backend(), denom.backend());
}
template <class To, class From>
@@ -455,7 +457,70 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
generic_interconvert_float2rational(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
}
-}}} // namespaces
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/)
+{
+ number<From> t(from);
+ number<To> result(numerator(t) / denominator(t));
+ to = result.backend();
+}
+
+template <class To, class From>
+void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<2>& /*radix*/)
+{
+ typedef typename From::exponent_type exponent_type;
+ static const exponent_type shift = std::numeric_limits<boost::long_long_type>::digits;
+ exponent_type e;
+ number<To> num(0u);
+ number<From> val(from);
+ val = frexp(val, &e);
+ while(e > 0)
+ {
+ int s = (std::min)(e, shift);
+ val = ldexp(val, s);
+ e -= s;
+ boost::long_long_type ll = boost::math::lltrunc(val);
+ val -= ll;
+ num <<= s;
+ num += ll;
+ }
+ to = num.backend();
+}
+
+template <class To, class From, int Radix>
+void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<Radix>& /*radix*/)
+{
+ //
+ // This is almost the same as the binary case above, but we have to use
+ // scalbn and ilogb rather than ldexp and frexp, we also only extract
+ // one Radix digit at a time which is terribly inefficient!
+ //
+ typename From::exponent_type e;
+ number<To> num(0u);
+ number<From> val(from);
+ e = ilogb(val);
+ val = scalbn(val, -e);
+ while(e >= 0)
+ {
+ boost::long_long_type ll = boost::math::lltrunc(val);
+ val -= ll;
+ val = scalbn(val, 1);
+ num *= Radix;
+ num += ll;
+ --e;
+ }
+ to = num.backend();
+}
+
+template <class To, class From>
+void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
+{
+ generic_interconvert_float2int(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
+}
+
+}
+}
+} // namespaces
#ifdef BOOST_MSVC
#pragma warning(pop)