Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/multiprecision/detail/generic_interconvert.hpp @ 16:2665513ce2d3
Add boost headers
| author | Chris Cannam |
|---|---|
| date | Tue, 05 Aug 2014 11:11:38 +0100 |
| parents | |
| children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
| 15:663ca0da4350 | 16:2665513ce2d3 |
|---|---|
| 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 namespace boost{ namespace multiprecision{ namespace detail{ | |
| 12 | |
| 13 template <class To, class From> | |
| 14 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/) | |
| 15 { | |
| 16 using default_ops::eval_get_sign; | |
| 17 using default_ops::eval_bitwise_and; | |
| 18 using default_ops::eval_convert_to; | |
| 19 using default_ops::eval_right_shift; | |
| 20 using default_ops::eval_ldexp; | |
| 21 using default_ops::eval_add; | |
| 22 // smallest unsigned type handled natively by "From" is likely to be it's limb_type: | |
| 23 typedef typename canonical<unsigned char, From>::type limb_type; | |
| 24 // get the corresponding type that we can assign to "To": | |
| 25 typedef typename canonical<limb_type, To>::type to_type; | |
| 26 From t(from); | |
| 27 bool is_neg = eval_get_sign(t) < 0; | |
| 28 if(is_neg) | |
| 29 t.negate(); | |
| 30 // Pick off the first limb: | |
| 31 limb_type limb; | |
| 32 limb_type mask = ~static_cast<limb_type>(0); | |
| 33 From fl; | |
| 34 eval_bitwise_and(fl, t, mask); | |
| 35 eval_convert_to(&limb, fl); | |
| 36 to = static_cast<to_type>(limb); | |
| 37 eval_right_shift(t, std::numeric_limits<limb_type>::digits); | |
| 38 // | |
| 39 // Then keep picking off more limbs until "t" is zero: | |
| 40 // | |
| 41 To l; | |
| 42 unsigned shift = std::numeric_limits<limb_type>::digits; | |
| 43 while(!eval_is_zero(t)) | |
| 44 { | |
| 45 eval_bitwise_and(fl, t, mask); | |
| 46 eval_convert_to(&limb, fl); | |
| 47 l = static_cast<to_type>(limb); | |
| 48 eval_right_shift(t, std::numeric_limits<limb_type>::digits); | |
| 49 eval_ldexp(l, l, shift); | |
| 50 eval_add(to, l); | |
| 51 shift += std::numeric_limits<limb_type>::digits; | |
| 52 } | |
| 53 // | |
| 54 // Finish off by setting the sign: | |
| 55 // | |
| 56 if(is_neg) | |
| 57 to.negate(); | |
| 58 } | |
| 59 | |
| 60 template <class To, class From> | |
| 61 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/) | |
| 62 { | |
| 63 using default_ops::eval_get_sign; | |
| 64 using default_ops::eval_bitwise_and; | |
| 65 using default_ops::eval_convert_to; | |
| 66 using default_ops::eval_right_shift; | |
| 67 using default_ops::eval_left_shift; | |
| 68 using default_ops::eval_bitwise_or; | |
| 69 using default_ops::eval_is_zero; | |
| 70 // smallest unsigned type handled natively by "From" is likely to be it's limb_type: | |
| 71 typedef typename canonical<unsigned char, From>::type limb_type; | |
| 72 // get the corresponding type that we can assign to "To": | |
| 73 typedef typename canonical<limb_type, To>::type to_type; | |
| 74 From t(from); | |
| 75 bool is_neg = eval_get_sign(t) < 0; | |
| 76 if(is_neg) | |
| 77 t.negate(); | |
| 78 // Pick off the first limb: | |
| 79 limb_type limb; | |
| 80 limb_type mask = static_cast<limb_type>(~static_cast<limb_type>(0)); | |
| 81 From fl; | |
| 82 eval_bitwise_and(fl, t, mask); | |
| 83 eval_convert_to(&limb, fl); | |
| 84 to = static_cast<to_type>(limb); | |
| 85 eval_right_shift(t, std::numeric_limits<limb_type>::digits); | |
| 86 // | |
| 87 // Then keep picking off more limbs until "t" is zero: | |
| 88 // | |
| 89 To l; | |
| 90 unsigned shift = std::numeric_limits<limb_type>::digits; | |
| 91 while(!eval_is_zero(t)) | |
| 92 { | |
| 93 eval_bitwise_and(fl, t, mask); | |
| 94 eval_convert_to(&limb, fl); | |
| 95 l = static_cast<to_type>(limb); | |
| 96 eval_right_shift(t, std::numeric_limits<limb_type>::digits); | |
| 97 eval_left_shift(l, shift); | |
| 98 eval_bitwise_or(to, l); | |
| 99 shift += std::numeric_limits<limb_type>::digits; | |
| 100 } | |
| 101 // | |
| 102 // Finish off by setting the sign: | |
| 103 // | |
| 104 if(is_neg) | |
| 105 to.negate(); | |
| 106 } | |
| 107 | |
| 108 template <class To, class From> | |
| 109 void 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*/) | |
| 110 { | |
| 111 #ifdef BOOST_MSVC | |
| 112 #pragma warning(push) | |
| 113 #pragma warning(disable:4127) | |
| 114 #endif | |
| 115 // | |
| 116 // The code here only works when the radix of "From" is 2, we could try shifting by other | |
| 117 // radixes but it would complicate things.... use a string conversion when the radix is other | |
| 118 // than 2: | |
| 119 // | |
| 120 if(std::numeric_limits<number<From> >::radix != 2) | |
| 121 { | |
| 122 to = from.str(0, std::ios_base::fmtflags()).c_str(); | |
| 123 return; | |
| 124 } | |
| 125 | |
| 126 | |
| 127 typedef typename canonical<unsigned char, To>::type ui_type; | |
| 128 | |
| 129 using default_ops::eval_fpclassify; | |
| 130 using default_ops::eval_add; | |
| 131 using default_ops::eval_subtract; | |
| 132 using default_ops::eval_convert_to; | |
| 133 | |
| 134 // | |
| 135 // First classify the input, then handle the special cases: | |
| 136 // | |
| 137 int c = eval_fpclassify(from); | |
| 138 | |
| 139 if(c == FP_ZERO) | |
| 140 { | |
| 141 to = ui_type(0); | |
| 142 return; | |
| 143 } | |
| 144 else if(c == FP_NAN) | |
| 145 { | |
| 146 to = "nan"; | |
| 147 return; | |
| 148 } | |
| 149 else if(c == FP_INFINITE) | |
| 150 { | |
| 151 to = "inf"; | |
| 152 if(eval_get_sign(from) < 0) | |
| 153 to.negate(); | |
| 154 return; | |
| 155 } | |
| 156 | |
| 157 typename From::exponent_type e; | |
| 158 From f, term; | |
| 159 to = ui_type(0); | |
| 160 | |
| 161 eval_frexp(f, from, &e); | |
| 162 | |
| 163 static const int shift = std::numeric_limits<boost::intmax_t>::digits - 1; | |
| 164 | |
| 165 while(!eval_is_zero(f)) | |
| 166 { | |
| 167 // extract int sized bits from f: | |
| 168 eval_ldexp(f, f, shift); | |
| 169 eval_floor(term, f); | |
| 170 e -= shift; | |
| 171 eval_ldexp(to, to, shift); | |
| 172 typename boost::multiprecision::detail::canonical<boost::intmax_t, To>::type ll; | |
| 173 eval_convert_to(&ll, term); | |
| 174 eval_add(to, ll); | |
| 175 eval_subtract(f, term); | |
| 176 } | |
| 177 typedef typename To::exponent_type to_exponent; | |
| 178 if((e > (std::numeric_limits<to_exponent>::max)()) || (e < (std::numeric_limits<to_exponent>::min)())) | |
| 179 { | |
| 180 to = "inf"; | |
| 181 if(eval_get_sign(from) < 0) | |
| 182 to.negate(); | |
| 183 return; | |
| 184 } | |
| 185 eval_ldexp(to, to, static_cast<to_exponent>(e)); | |
| 186 #ifdef BOOST_MSVC | |
| 187 #pragma warning(pop) | |
| 188 #endif | |
| 189 } | |
| 190 | |
| 191 template <class To, class From> | |
| 192 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/) | |
| 193 { | |
| 194 typedef typename component_type<number<To> >::type to_component_type; | |
| 195 | |
| 196 number<From> t(from); | |
| 197 to_component_type n(numerator(t)), d(denominator(t)); | |
| 198 using default_ops::assign_components; | |
| 199 assign_components(to, n.backend(), d.backend()); | |
| 200 } | |
| 201 | |
| 202 template <class To, class From> | |
| 203 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/) | |
| 204 { | |
| 205 typedef typename component_type<number<To> >::type to_component_type; | |
| 206 | |
| 207 number<From> t(from); | |
| 208 to_component_type n(t), d(1); | |
| 209 using default_ops::assign_components; | |
| 210 assign_components(to, n.backend(), d.backend()); | |
| 211 } | |
| 212 | |
| 213 template <class To, class From> | |
| 214 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*/) | |
| 215 { | |
| 216 typedef typename component_type<number<From> >::type from_component_type; | |
| 217 using default_ops::eval_divide; | |
| 218 | |
| 219 number<From> t(from); | |
| 220 from_component_type n(numerator(t)), d(denominator(t)); | |
| 221 number<To> fn(n), fd(d); | |
| 222 eval_divide(to, fn.backend(), fd.backend()); | |
| 223 } | |
| 224 | |
| 225 }}} // namespaces | |
| 226 | |
| 227 #endif // BOOST_MP_GENERIC_INTERCONVERT_HPP | |
| 228 |
