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 |