Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/multiprecision/rational_adaptor.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_ | |
5 | |
6 #ifndef BOOST_MATH_RATIONAL_ADAPTER_HPP | |
7 #define BOOST_MATH_RATIONAL_ADAPTER_HPP | |
8 | |
9 #include <iostream> | |
10 #include <iomanip> | |
11 #include <sstream> | |
12 #include <boost/cstdint.hpp> | |
13 #include <boost/multiprecision/number.hpp> | |
14 #ifdef BOOST_MSVC | |
15 # pragma warning(push) | |
16 # pragma warning(disable:4512 4127) | |
17 #endif | |
18 #include <boost/rational.hpp> | |
19 #ifdef BOOST_MSVC | |
20 # pragma warning(pop) | |
21 #endif | |
22 | |
23 namespace boost{ | |
24 namespace multiprecision{ | |
25 namespace backends{ | |
26 | |
27 template <class IntBackend> | |
28 struct rational_adaptor | |
29 { | |
30 typedef number<IntBackend> integer_type; | |
31 typedef boost::rational<integer_type> rational_type; | |
32 | |
33 typedef typename IntBackend::signed_types signed_types; | |
34 typedef typename IntBackend::unsigned_types unsigned_types; | |
35 typedef typename IntBackend::float_types float_types; | |
36 | |
37 rational_adaptor(){} | |
38 rational_adaptor(const rational_adaptor& o) | |
39 { | |
40 m_value = o.m_value; | |
41 } | |
42 rational_adaptor(const IntBackend& o) : m_value(o) {} | |
43 | |
44 template <class U> | |
45 rational_adaptor(const U& u, typename enable_if_c<is_convertible<U, IntBackend>::value>::type* = 0) | |
46 : m_value(IntBackend(u)){} | |
47 template <class U> | |
48 explicit rational_adaptor(const U& u, | |
49 typename enable_if_c< | |
50 boost::multiprecision::detail::is_explicitly_convertible<U, IntBackend>::value && !is_convertible<U, IntBackend>::value | |
51 >::type* = 0) | |
52 : m_value(IntBackend(u)){} | |
53 template <class U> | |
54 typename enable_if_c<(boost::multiprecision::detail::is_explicitly_convertible<U, IntBackend>::value && !is_arithmetic<U>::value), rational_adaptor&>::type operator = (const U& u) | |
55 { | |
56 m_value = IntBackend(u); | |
57 } | |
58 | |
59 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
60 rational_adaptor(rational_adaptor&& o) : m_value(o.m_value) {} | |
61 rational_adaptor(IntBackend&& o) : m_value(o) {} | |
62 rational_adaptor& operator = (rational_adaptor&& o) | |
63 { | |
64 m_value = static_cast<rational_type&&>(o.m_value); | |
65 return *this; | |
66 } | |
67 #endif | |
68 rational_adaptor& operator = (const rational_adaptor& o) | |
69 { | |
70 m_value = o.m_value; | |
71 return *this; | |
72 } | |
73 rational_adaptor& operator = (const IntBackend& o) | |
74 { | |
75 m_value = o; | |
76 return *this; | |
77 } | |
78 template <class Int> | |
79 typename enable_if<is_integral<Int>, rational_adaptor&>::type operator = (Int i) | |
80 { | |
81 m_value = i; | |
82 return *this; | |
83 } | |
84 template <class Float> | |
85 typename enable_if<is_floating_point<Float>, rational_adaptor&>::type operator = (Float i) | |
86 { | |
87 int e; | |
88 Float f = std::frexp(i, &e); | |
89 f = std::ldexp(f, std::numeric_limits<Float>::digits); | |
90 e -= std::numeric_limits<Float>::digits; | |
91 integer_type num(f); | |
92 integer_type denom(1u); | |
93 if(e > 0) | |
94 { | |
95 num <<= e; | |
96 } | |
97 else if(e < 0) | |
98 { | |
99 denom <<= -e; | |
100 } | |
101 m_value.assign(num, denom); | |
102 return *this; | |
103 } | |
104 rational_adaptor& operator = (const char* s) | |
105 { | |
106 std::string s1; | |
107 multiprecision::number<IntBackend> v1, v2; | |
108 char c; | |
109 bool have_hex = false; | |
110 const char* p = s; // saved for later | |
111 | |
112 while((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) | |
113 { | |
114 if(c == 'x' || c == 'X') | |
115 have_hex = true; | |
116 s1.append(1, c); | |
117 ++s; | |
118 } | |
119 v1.assign(s1); | |
120 s1.erase(); | |
121 if(c == '/') | |
122 { | |
123 ++s; | |
124 while((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) | |
125 { | |
126 if(c == 'x' || c == 'X') | |
127 have_hex = true; | |
128 s1.append(1, c); | |
129 ++s; | |
130 } | |
131 v2.assign(s1); | |
132 } | |
133 else | |
134 v2 = 1; | |
135 if(*s) | |
136 { | |
137 BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Could parse the string \"") + p + std::string("\" as a valid rational number."))); | |
138 } | |
139 data().assign(v1, v2); | |
140 return *this; | |
141 } | |
142 void swap(rational_adaptor& o) | |
143 { | |
144 std::swap(m_value, o.m_value); | |
145 } | |
146 std::string str(std::streamsize digits, std::ios_base::fmtflags f)const | |
147 { | |
148 // | |
149 // We format the string ourselves so we can match what GMP's mpq type does: | |
150 // | |
151 std::string result = data().numerator().str(digits, f); | |
152 if(data().denominator() != 1) | |
153 { | |
154 result.append(1, '/'); | |
155 result.append(data().denominator().str(digits, f)); | |
156 } | |
157 return result; | |
158 } | |
159 void negate() | |
160 { | |
161 m_value = -m_value; | |
162 } | |
163 int compare(const rational_adaptor& o)const | |
164 { | |
165 return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0); | |
166 } | |
167 template <class Arithmatic> | |
168 typename enable_if<is_arithmetic<Arithmatic>, int>::type compare(Arithmatic i)const | |
169 { | |
170 return m_value > i ? 1 : (m_value < i ? -1 : 0); | |
171 } | |
172 rational_type& data() { return m_value; } | |
173 const rational_type& data()const { return m_value; } | |
174 | |
175 template <class Archive> | |
176 void serialize(Archive& ar, const mpl::true_&) | |
177 { | |
178 // Saving | |
179 integer_type n(m_value.numerator()), d(m_value.denominator()); | |
180 ar & n; | |
181 ar & d; | |
182 } | |
183 template <class Archive> | |
184 void serialize(Archive& ar, const mpl::false_&) | |
185 { | |
186 // Loading | |
187 integer_type n, d; | |
188 ar & n; | |
189 ar & d; | |
190 m_value.assign(n, d); | |
191 } | |
192 template <class Archive> | |
193 void serialize(Archive& ar, const unsigned int /*version*/) | |
194 { | |
195 typedef typename Archive::is_saving tag; | |
196 serialize(ar, tag()); | |
197 } | |
198 private: | |
199 rational_type m_value; | |
200 }; | |
201 | |
202 template <class IntBackend> | |
203 inline void eval_add(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o) | |
204 { | |
205 result.data() += o.data(); | |
206 } | |
207 template <class IntBackend> | |
208 inline void eval_subtract(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o) | |
209 { | |
210 result.data() -= o.data(); | |
211 } | |
212 template <class IntBackend> | |
213 inline void eval_multiply(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o) | |
214 { | |
215 result.data() *= o.data(); | |
216 } | |
217 template <class IntBackend> | |
218 inline void eval_divide(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o) | |
219 { | |
220 using default_ops::eval_is_zero; | |
221 if(eval_is_zero(o)) | |
222 { | |
223 BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero.")); | |
224 } | |
225 result.data() /= o.data(); | |
226 } | |
227 | |
228 template <class R, class IntBackend> | |
229 inline void eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend) | |
230 { | |
231 *result = backend.data().numerator().template convert_to<R>(); | |
232 *result /= backend.data().denominator().template convert_to<R>(); | |
233 } | |
234 | |
235 template <class IntBackend> | |
236 inline bool eval_is_zero(const rational_adaptor<IntBackend>& val) | |
237 { | |
238 return eval_is_zero(val.data().numerator().backend()); | |
239 } | |
240 template <class IntBackend> | |
241 inline int eval_get_sign(const rational_adaptor<IntBackend>& val) | |
242 { | |
243 return eval_get_sign(val.data().numerator().backend()); | |
244 } | |
245 | |
246 template<class IntBackend, class V> | |
247 inline void assign_components(rational_adaptor<IntBackend>& result, const V& v1, const V& v2) | |
248 { | |
249 result.data().assign(v1, v2); | |
250 } | |
251 | |
252 } // namespace backends | |
253 | |
254 template<class IntBackend> | |
255 struct expression_template_default<backends::rational_adaptor<IntBackend> > : public expression_template_default<IntBackend> {}; | |
256 | |
257 template<class IntBackend> | |
258 struct number_category<backends::rational_adaptor<IntBackend> > : public mpl::int_<number_kind_rational>{}; | |
259 | |
260 using boost::multiprecision::backends::rational_adaptor; | |
261 | |
262 template <class T> | |
263 struct component_type<rational_adaptor<T> > | |
264 { | |
265 typedef number<T> type; | |
266 }; | |
267 | |
268 template <class IntBackend, expression_template_option ET> | |
269 inline number<IntBackend, ET> numerator(const number<rational_adaptor<IntBackend>, ET>& val) | |
270 { | |
271 return val.backend().data().numerator(); | |
272 } | |
273 template <class IntBackend, expression_template_option ET> | |
274 inline number<IntBackend, ET> denominator(const number<rational_adaptor<IntBackend>, ET>& val) | |
275 { | |
276 return val.backend().data().denominator(); | |
277 } | |
278 | |
279 #ifdef BOOST_NO_SFINAE_EXPR | |
280 | |
281 namespace detail{ | |
282 | |
283 template<class U, class IntBackend> | |
284 struct is_explicitly_convertible<U, rational_adaptor<IntBackend> > : public is_explicitly_convertible<U, IntBackend> {}; | |
285 | |
286 } | |
287 | |
288 #endif | |
289 | |
290 }} // namespaces | |
291 | |
292 | |
293 namespace std{ | |
294 | |
295 template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates> | |
296 class numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> > : public std::numeric_limits<boost::multiprecision::number<IntBackend, ExpressionTemplates> > | |
297 { | |
298 typedef std::numeric_limits<boost::multiprecision::number<IntBackend> > base_type; | |
299 typedef boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend> > number_type; | |
300 public: | |
301 BOOST_STATIC_CONSTEXPR bool is_integer = false; | |
302 BOOST_STATIC_CONSTEXPR bool is_exact = true; | |
303 BOOST_STATIC_CONSTEXPR number_type (min)() { return (base_type::min)(); } | |
304 BOOST_STATIC_CONSTEXPR number_type (max)() { return (base_type::max)(); } | |
305 BOOST_STATIC_CONSTEXPR number_type lowest() { return -(max)(); } | |
306 BOOST_STATIC_CONSTEXPR number_type epsilon() { return base_type::epsilon(); } | |
307 BOOST_STATIC_CONSTEXPR number_type round_error() { return epsilon() / 2; } | |
308 BOOST_STATIC_CONSTEXPR number_type infinity() { return base_type::infinity(); } | |
309 BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return base_type::quiet_NaN(); } | |
310 BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return base_type::signaling_NaN(); } | |
311 BOOST_STATIC_CONSTEXPR number_type denorm_min() { return base_type::denorm_min(); } | |
312 }; | |
313 | |
314 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
315 | |
316 template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates> | |
317 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_integer; | |
318 template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates> | |
319 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_exact; | |
320 | |
321 #endif | |
322 | |
323 | |
324 } | |
325 | |
326 #endif |