comparison DEPENDENCIES/generic/include/boost/multiprecision/number.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_MATH_EXTENDED_REAL_HPP
7 #define BOOST_MATH_EXTENDED_REAL_HPP
8
9 #include <boost/cstdint.hpp>
10 #include <boost/mpl/max.hpp>
11 #include <boost/mpl/plus.hpp>
12 #include <boost/mpl/or.hpp>
13 #include <boost/mpl/find_if.hpp>
14 #include <boost/assert.hpp>
15 #include <boost/type_traits/remove_pointer.hpp>
16 #include <boost/type_traits/is_signed.hpp>
17 #include <boost/type_traits/is_unsigned.hpp>
18 #include <boost/type_traits/is_floating_point.hpp>
19 #include <boost/type_traits/is_integral.hpp>
20 #include <boost/type_traits/make_unsigned.hpp>
21 #include <boost/throw_exception.hpp>
22 #include <boost/multiprecision/detail/generic_interconvert.hpp>
23 #include <boost/multiprecision/detail/number_compare.hpp>
24 #include <boost/multiprecision/traits/is_restricted_conversion.hpp>
25 #include <istream> // stream operators
26 #include <cstdio> // EOF
27
28 namespace boost{ namespace multiprecision{
29
30 #ifdef BOOST_MSVC
31 // warning C4127: conditional expression is constant
32 // warning C4714: function marked as __forceinline not inlined
33 #pragma warning(push)
34 #pragma warning(disable:4127 4714)
35 #endif
36
37 template <class Backend, expression_template_option ExpressionTemplates>
38 class number
39 {
40 typedef number<Backend, ExpressionTemplates> self_type;
41 public:
42 typedef Backend backend_type;
43 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number() BOOST_NOEXCEPT_IF(noexcept(Backend())) {}
44 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e) BOOST_NOEXCEPT_IF(noexcept(Backend(static_cast<const Backend&>(std::declval<Backend>())))) : m_backend(e.m_backend){}
45 template <class V>
46 BOOST_MP_FORCEINLINE number(const V& v, typename boost::enable_if_c<
47 (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value)
48 && !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
49 && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
50 >::type* = 0)
51 {
52 m_backend = canonical_value(v);
53 }
54 template <class V>
55 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
56 is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
57 && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
58 >::type* = 0)
59 : m_backend(canonical_value(v)) {}
60 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e, unsigned digits10)
61 : m_backend(e.m_backend, digits10){}
62 template <class V>
63 explicit BOOST_MP_FORCEINLINE number(const V& v, typename boost::enable_if_c<
64 (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value)
65 && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
66 && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
67 >::type* = 0)
68 {
69 m_backend = canonical_value(v);
70 }
71 template <class V>
72 explicit BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
73 detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
74 && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
75 || !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)
76 >::type* = 0)
77 : m_backend(canonical_value(v)) {}
78 /*
79 //
80 // This conflicts with component based initialization (for rational and complex types)
81 // which is arguably more useful. Disabled for now.
82 //
83 template <class V>
84 number(V v, unsigned digits10, typename boost::enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* dummy1 = 0)
85 {
86 m_backend.precision(digits10);
87 m_backend = canonical_value(v);
88 }
89 */
90 template<expression_template_option ET>
91 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number<Backend, ET>& val)
92 BOOST_NOEXCEPT_IF(noexcept(Backend(static_cast<const Backend&>(std::declval<Backend>())))) : m_backend(val.backend()) {}
93
94 template <class Other, expression_template_option ET>
95 BOOST_MP_FORCEINLINE number(const number<Other, ET>& val,
96 typename boost::enable_if_c<(boost::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)
97 BOOST_NOEXCEPT_IF(noexcept(Backend(static_cast<const Other&>(std::declval<Other>()))))
98 : m_backend(val.backend()) {}
99
100 template <class Other, expression_template_option ET>
101 explicit number(const number<Other, ET>& val, typename boost::enable_if_c<
102 (!detail::is_explicitly_convertible<Other, Backend>::value)
103 >::type* = 0)
104 {
105 //
106 // Attempt a generic interconvertion:
107 //
108 detail::generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
109 }
110 template <class Other, expression_template_option ET>
111 explicit BOOST_MP_FORCEINLINE number(const number<Other, ET>& val, typename boost::enable_if_c<
112 (detail::is_explicitly_convertible<Other, Backend>::value
113 && (detail::is_restricted_conversion<Other, Backend>::value || !boost::is_convertible<Other, Backend>::value))
114 >::type* = 0) BOOST_NOEXCEPT_IF(noexcept(Backend(static_cast<const Other&>(std::declval<Other>()))))
115 : m_backend(val.backend()) {}
116
117 template <class V>
118 BOOST_MP_FORCEINLINE number(V v1, V v2, typename boost::enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* = 0)
119 {
120 using default_ops::assign_components;
121 assign_components(m_backend, canonical_value(v1), canonical_value(v2));
122 }
123 template <class Other, expression_template_option ET>
124 BOOST_MP_FORCEINLINE number(const number<Other, ET>& v1, const number<Other, ET>& v2, typename boost::enable_if<boost::is_convertible<Other, Backend> >::type* = 0)
125 {
126 using default_ops::assign_components;
127 assign_components(m_backend, v1.backend(), v2.backend());
128 }
129
130 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
131 typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
132 {
133 typedef typename is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::type tag_type;
134 do_assign(e, tag_type());
135 return *this;
136 }
137 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
138 number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
139 {
140 typedef typename is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::type tag_type;
141 do_assign(e, tag_type());
142 return *this;
143 }
144
145 BOOST_MP_FORCEINLINE number& operator=(const number& e)
146 BOOST_NOEXCEPT_IF(noexcept(std::declval<Backend>() = static_cast<const Backend&>(std::declval<Backend>())))
147 {
148 m_backend = e.m_backend;
149 return *this;
150 }
151
152 template <class V>
153 BOOST_MP_FORCEINLINE typename boost::enable_if<is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
154 operator=(const V& v)
155 BOOST_NOEXCEPT_IF(noexcept(std::declval<Backend>() = static_cast<typename boost::multiprecision::detail::canonical<V, Backend>::type const&>(std::declval<typename boost::multiprecision::detail::canonical<V, Backend>::type>())))
156 {
157 m_backend = canonical_value(v);
158 return *this;
159 }
160 template <class V>
161 BOOST_MP_FORCEINLINE number<Backend, ExpressionTemplates>& assign(const V& v)
162 BOOST_NOEXCEPT_IF(noexcept(std::declval<Backend>() = static_cast<typename boost::multiprecision::detail::canonical<V, Backend>::type const&>(std::declval<typename boost::multiprecision::detail::canonical<V, Backend>::type>())))
163 {
164 m_backend = canonical_value(v);
165 return *this;
166 }
167 template <class Other, expression_template_option ET>
168 typename boost::disable_if<boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>, number<Backend, ExpressionTemplates>& >::type
169 assign(const number<Other, ET>& v)
170 {
171 //
172 // Attempt a generic interconvertion:
173 //
174 detail::generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
175 return *this;
176 }
177
178 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
179 number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
180 {
181 *this = e;
182 }
183 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
184 explicit number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
185 typename boost::enable_if_c<!is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value
186 && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
187 {
188 assign(e);
189 }
190
191 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
192 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(number&& r)
193 BOOST_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend>())))
194 : m_backend(static_cast<Backend&&>(r.m_backend)){}
195 BOOST_MP_FORCEINLINE number& operator=(number&& r) BOOST_NOEXCEPT
196 {
197 m_backend = static_cast<Backend&&>(r.m_backend);
198 return *this;
199 }
200 #endif
201
202 number& operator+=(const self_type& val)
203 {
204 do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
205 return *this;
206 }
207
208 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
209 number& operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
210 {
211 // Create a copy if e contains this, but not if we're just doing a
212 // x += x
213 if(contains_self(e) && !is_self(e))
214 {
215 self_type temp(e);
216 do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
217 }
218 else
219 {
220 do_add(e, tag());
221 }
222 return *this;
223 }
224
225 template <class Arg1, class Arg2, class Arg3, class Arg4>
226 number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
227 {
228 //
229 // Fused multiply-add:
230 //
231 using default_ops::eval_multiply_add;
232 eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
233 return *this;
234 }
235
236 template <class V>
237 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
238 operator+=(const V& v)
239 {
240 using default_ops::eval_add;
241 eval_add(m_backend, canonical_value(v));
242 return *this;
243 }
244
245 number& operator-=(const self_type& val)
246 {
247 do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
248 return *this;
249 }
250
251 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
252 number& operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
253 {
254 // Create a copy if e contains this:
255 if(contains_self(e))
256 {
257 self_type temp(e);
258 do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
259 }
260 else
261 {
262 do_subtract(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
263 }
264 return *this;
265 }
266
267 template <class V>
268 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
269 operator-=(const V& v)
270 {
271 using default_ops::eval_subtract;
272 eval_subtract(m_backend, canonical_value(v));
273 return *this;
274 }
275
276 template <class Arg1, class Arg2, class Arg3, class Arg4>
277 number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
278 {
279 //
280 // Fused multiply-subtract:
281 //
282 using default_ops::eval_multiply_subtract;
283 eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
284 return *this;
285 }
286
287
288 number& operator *= (const self_type& e)
289 {
290 do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
291 return *this;
292 }
293
294 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
295 number& operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
296 {
297 // Create a temporary if the RHS references *this, but not
298 // if we're just doing an x *= x;
299 if(contains_self(e) && !is_self(e))
300 {
301 self_type temp(e);
302 do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
303 }
304 else
305 {
306 do_multiplies(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
307 }
308 return *this;
309 }
310
311 template <class V>
312 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
313 operator*=(const V& v)
314 {
315 using default_ops::eval_multiply;
316 eval_multiply(m_backend, canonical_value(v));
317 return *this;
318 }
319
320 number& operator%=(const self_type& e)
321 {
322 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
323 do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());
324 return *this;
325 }
326 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
327 number& operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
328 {
329 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
330 // Create a temporary if the RHS references *this:
331 if(contains_self(e))
332 {
333 self_type temp(e);
334 do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
335 }
336 else
337 {
338 do_modulus(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
339 }
340 return *this;
341 }
342 template <class V>
343 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
344 operator%=(const V& v)
345 {
346 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
347 using default_ops::eval_modulus;
348 eval_modulus(m_backend, canonical_value(v));
349 return *this;
350 }
351
352 //
353 // These operators are *not* proto-ized.
354 // The issue is that the increment/decrement must happen
355 // even if the result of the operator *is never used*.
356 // Possibly we could modify our expression wrapper to
357 // execute the increment/decrement on destruction, but
358 // correct implementation will be tricky, so defered for now...
359 //
360 BOOST_MP_FORCEINLINE number& operator++()
361 {
362 using default_ops::eval_increment;
363 eval_increment(m_backend);
364 return *this;
365 }
366
367 BOOST_MP_FORCEINLINE number& operator--()
368 {
369 using default_ops::eval_decrement;
370 eval_decrement(m_backend);
371 return *this;
372 }
373
374 inline number operator++(int)
375 {
376 using default_ops::eval_increment;
377 self_type temp(*this);
378 eval_increment(m_backend);
379 return BOOST_MP_MOVE(temp);
380 }
381
382 inline number operator--(int)
383 {
384 using default_ops::eval_decrement;
385 self_type temp(*this);
386 eval_decrement(m_backend);
387 return BOOST_MP_MOVE(temp);
388 }
389
390 template <class V>
391 BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator <<= (V val)
392 {
393 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");
394 detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed<V>());
395 eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
396 return *this;
397 }
398
399 template <class V>
400 BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator >>= (V val)
401 {
402 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");
403 detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed<V>());
404 eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
405 return *this;
406 }
407
408 BOOST_MP_FORCEINLINE number& operator /= (const self_type& e)
409 {
410 do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
411 return *this;
412 }
413
414 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
415 number& operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
416 {
417 // Create a temporary if the RHS references *this:
418 if(contains_self(e))
419 {
420 self_type temp(e);
421 do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
422 }
423 else
424 {
425 do_divide(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
426 }
427 return *this;
428 }
429
430 template <class V>
431 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
432 operator/=(const V& v)
433 {
434 using default_ops::eval_divide;
435 eval_divide(m_backend, canonical_value(v));
436 return *this;
437 }
438
439 BOOST_MP_FORCEINLINE number& operator&=(const self_type& e)
440 {
441 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
442 do_bitwise_and(detail::expression<detail::terminal, self_type>(e), detail::terminal());
443 return *this;
444 }
445
446 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
447 number& operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
448 {
449 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
450 // Create a temporary if the RHS references *this, but not
451 // if we're just doing an x &= x;
452 if(contains_self(e) && !is_self(e))
453 {
454 self_type temp(e);
455 do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
456 }
457 else
458 {
459 do_bitwise_and(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
460 }
461 return *this;
462 }
463
464 template <class V>
465 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
466 operator&=(const V& v)
467 {
468 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
469 using default_ops::eval_bitwise_and;
470 eval_bitwise_and(m_backend, canonical_value(v));
471 return *this;
472 }
473
474 BOOST_MP_FORCEINLINE number& operator|=(const self_type& e)
475 {
476 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
477 do_bitwise_or(detail::expression<detail::terminal, self_type>(e), detail::terminal());
478 return *this;
479 }
480
481 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
482 number& operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
483 {
484 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
485 // Create a temporary if the RHS references *this, but not
486 // if we're just doing an x |= x;
487 if(contains_self(e) && !is_self(e))
488 {
489 self_type temp(e);
490 do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
491 }
492 else
493 {
494 do_bitwise_or(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
495 }
496 return *this;
497 }
498
499 template <class V>
500 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
501 operator|=(const V& v)
502 {
503 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
504 using default_ops::eval_bitwise_or;
505 eval_bitwise_or(m_backend, canonical_value(v));
506 return *this;
507 }
508
509 BOOST_MP_FORCEINLINE number& operator^=(const self_type& e)
510 {
511 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
512 do_bitwise_xor(detail::expression<detail::terminal, self_type>(e), detail::terminal());
513 return *this;
514 }
515
516 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
517 number& operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
518 {
519 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
520 if(contains_self(e))
521 {
522 self_type temp(e);
523 do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
524 }
525 else
526 {
527 do_bitwise_xor(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
528 }
529 return *this;
530 }
531
532 template <class V>
533 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
534 operator^=(const V& v)
535 {
536 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
537 using default_ops::eval_bitwise_xor;
538 eval_bitwise_xor(m_backend, canonical_value(v));
539 return *this;
540 }
541 //
542 // swap:
543 //
544 BOOST_MP_FORCEINLINE void swap(self_type& other) BOOST_NOEXCEPT
545 {
546 m_backend.swap(other.backend());
547 }
548 //
549 // Zero and sign:
550 //
551 BOOST_MP_FORCEINLINE bool is_zero()const
552 {
553 using default_ops::eval_is_zero;
554 return eval_is_zero(m_backend);
555 }
556 BOOST_MP_FORCEINLINE int sign()const
557 {
558 using default_ops::eval_get_sign;
559 return eval_get_sign(m_backend);
560 }
561 //
562 // String conversion functions:
563 //
564 std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0))const
565 {
566 return m_backend.str(digits, f);
567 }
568 template<class Archive>
569 void serialize(Archive & ar, const unsigned int /*version*/)
570 {
571 ar & m_backend;
572 }
573 private:
574 template <class T>
575 void convert_to_imp(T* result)const
576 {
577 using default_ops::eval_convert_to;
578 eval_convert_to(result, m_backend);
579 }
580 template <class B2, expression_template_option ET>
581 void convert_to_imp(number<B2, ET>* result)const
582 {
583 result->assign(*this);
584 }
585 void convert_to_imp(std::string* result)const
586 {
587 *result = this->str();
588 }
589 public:
590 template <class T>
591 T convert_to()const
592 {
593 T result;
594 convert_to_imp(&result);
595 return result;
596 }
597 //
598 // Use in boolean context, and explicit conversion operators:
599 //
600 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
601 # if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)
602 //
603 // Horrible workaround for gcc-4.6.x which always prefers the template
604 // operator bool() rather than the non-template operator when converting to
605 // an arithmetic type:
606 //
607 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
608 explicit operator T ()const
609 {
610 using default_ops::eval_is_zero;
611 return !eval_is_zero(backend());
612 }
613 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value, int>::type = 0>
614 explicit operator T ()const
615 {
616 return this->template convert_to<T>();
617 }
618 # else
619 template <class T>
620 explicit operator T()const
621 {
622 return this->template convert_to<T>();
623 }
624 BOOST_MP_FORCEINLINE explicit operator bool()const
625 {
626 return !is_zero();
627 }
628 explicit operator void()const {}
629 # endif
630 #else
631 typedef bool (self_type::*unmentionable_type)()const;
632
633 BOOST_MP_FORCEINLINE operator unmentionable_type()const
634 {
635 return is_zero() ? 0 : &self_type::is_zero;
636 }
637 #endif
638 //
639 // Default precision:
640 //
641 static unsigned default_precision() BOOST_NOEXCEPT
642 {
643 return Backend::default_precision();
644 }
645 static void default_precision(unsigned digits10)
646 {
647 Backend::default_precision(digits10);
648 }
649 unsigned precision()const BOOST_NOEXCEPT
650 {
651 return m_backend.precision();
652 }
653 void precision(unsigned digits10)
654 {
655 m_backend.precision(digits10);
656 }
657 //
658 // Comparison:
659 //
660 BOOST_MP_FORCEINLINE int compare(const number<Backend, ExpressionTemplates>& o)const
661 BOOST_NOEXCEPT_IF(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))
662 {
663 return m_backend.compare(o.m_backend);
664 }
665 template <class V>
666 BOOST_MP_FORCEINLINE typename boost::enable_if<is_arithmetic<V>, int>::type compare(const V& o)const
667 {
668 using default_ops::eval_get_sign;
669 if(o == 0)
670 return eval_get_sign(m_backend);
671 return m_backend.compare(canonical_value(o));
672 }
673 BOOST_MP_FORCEINLINE Backend& backend() BOOST_NOEXCEPT
674 {
675 return m_backend;
676 }
677 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& backend()const BOOST_NOEXCEPT
678 {
679 return m_backend;
680 }
681 private:
682 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
683 void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::true_&)
684 {
685 do_assign(e, tag());
686 }
687 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
688 void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::false_&)
689 {
690 // The result of the expression isn't the same type as this -
691 // create a temporary result and assign it to *this:
692 typedef typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type temp_type;
693 temp_type t(e);
694 this->assign(t);
695 }
696
697
698 template <class Exp>
699 void do_assign(const Exp& e, const detail::add_immediates&)
700 {
701 using default_ops::eval_add;
702 eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
703 }
704 template <class Exp>
705 void do_assign(const Exp& e, const detail::subtract_immediates&)
706 {
707 using default_ops::eval_subtract;
708 eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
709 }
710 template <class Exp>
711 void do_assign(const Exp& e, const detail::multiply_immediates&)
712 {
713 using default_ops::eval_multiply;
714 eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
715 }
716 template <class Exp>
717 void do_assign(const Exp& e, const detail::multiply_add&)
718 {
719 using default_ops::eval_multiply_add;
720 eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
721 }
722 template <class Exp>
723 void do_assign(const Exp& e, const detail::multiply_subtract&)
724 {
725 using default_ops::eval_multiply_subtract;
726 eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
727 }
728
729 template <class Exp>
730 void do_assign(const Exp& e, const detail::divide_immediates&)
731 {
732 using default_ops::eval_divide;
733 eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
734 }
735
736 template <class Exp>
737 void do_assign(const Exp& e, const detail::negate&)
738 {
739 typedef typename Exp::left_type left_type;
740 do_assign(e.left(), typename left_type::tag_type());
741 m_backend.negate();
742 }
743 template <class Exp>
744 void do_assign(const Exp& e, const detail::plus&)
745 {
746 typedef typename Exp::left_type left_type;
747 typedef typename Exp::right_type right_type;
748
749 static int const left_depth = left_type::depth;
750 static int const right_depth = right_type::depth;
751
752 bool bl = contains_self(e.left());
753 bool br = contains_self(e.right());
754
755 if(bl && is_self(e.left()))
756 {
757 // Ignore the left node, it's *this, just add the right:
758 do_add(e.right(), typename right_type::tag_type());
759 }
760 else if(br && is_self(e.right()))
761 {
762 // Ignore the right node, it's *this, just add the left:
763 do_add(e.left(), typename left_type::tag_type());
764 }
765 else if(bl && br)
766 {
767 self_type temp(e);
768 temp.m_backend.swap(this->m_backend);
769 }
770 else if(!br && (bl || (left_depth >= right_depth)))
771 { // br is always false, but if bl is true we must take the this branch:
772 do_assign(e.left(), typename left_type::tag_type());
773 do_add(e.right(), typename right_type::tag_type());
774 }
775 else
776 {
777 do_assign(e.right(), typename right_type::tag_type());
778 do_add(e.left(), typename left_type::tag_type());
779 }
780 }
781 template <class Exp>
782 void do_assign(const Exp& e, const detail::minus&)
783 {
784 typedef typename Exp::left_type left_type;
785 typedef typename Exp::right_type right_type;
786
787 static int const left_depth = left_type::depth;
788 static int const right_depth = right_type::depth;
789
790 bool bl = contains_self(e.left());
791 bool br = contains_self(e.right());
792
793 if(bl && is_self(e.left()))
794 {
795 // Ignore the left node, it's *this, just subtract the right:
796 do_subtract(e.right(), typename right_type::tag_type());
797 }
798 else if(br && is_self(e.right()))
799 {
800 // Ignore the right node, it's *this, just subtract the left and negate the result:
801 do_subtract(e.left(), typename left_type::tag_type());
802 m_backend.negate();
803 }
804 else if(bl && br)
805 {
806 self_type temp(e);
807 temp.m_backend.swap(this->m_backend);
808 }
809 else if(!br && (bl || (left_depth >= right_depth)))
810 { // br is always false, but if bl is true we must take the this branch:
811 do_assign(e.left(), typename left_type::tag_type());
812 do_subtract(e.right(), typename right_type::tag_type());
813 }
814 else
815 {
816 do_assign(e.right(), typename right_type::tag_type());
817 do_subtract(e.left(), typename left_type::tag_type());
818 m_backend.negate();
819 }
820 }
821 template <class Exp>
822 void do_assign(const Exp& e, const detail::multiplies&)
823 {
824 typedef typename Exp::left_type left_type;
825 typedef typename Exp::right_type right_type;
826
827 static int const left_depth = left_type::depth;
828 static int const right_depth = right_type::depth;
829
830 bool bl = contains_self(e.left());
831 bool br = contains_self(e.right());
832
833 if(bl && is_self(e.left()))
834 {
835 // Ignore the left node, it's *this, just add the right:
836 do_multiplies(e.right(), typename right_type::tag_type());
837 }
838 else if(br && is_self(e.right()))
839 {
840 // Ignore the right node, it's *this, just add the left:
841 do_multiplies(e.left(), typename left_type::tag_type());
842 }
843 else if(bl && br)
844 {
845 self_type temp(e);
846 temp.m_backend.swap(this->m_backend);
847 }
848 else if(!br && (bl || (left_depth >= right_depth)))
849 { // br is always false, but if bl is true we must take the this branch:
850 do_assign(e.left(), typename left_type::tag_type());
851 do_multiplies(e.right(), typename right_type::tag_type());
852 }
853 else
854 {
855 do_assign(e.right(), typename right_type::tag_type());
856 do_multiplies(e.left(), typename left_type::tag_type());
857 }
858 }
859 template <class Exp>
860 void do_assign(const Exp& e, const detail::divides&)
861 {
862 typedef typename Exp::left_type left_type;
863 typedef typename Exp::right_type right_type;
864
865 bool bl = contains_self(e.left());
866 bool br = contains_self(e.right());
867
868 if(bl && is_self(e.left()))
869 {
870 // Ignore the left node, it's *this, just add the right:
871 do_divide(e.right(), typename right_type::tag_type());
872 }
873 else if(br)
874 {
875 self_type temp(e);
876 temp.m_backend.swap(this->m_backend);
877 }
878 else
879 {
880 do_assign(e.left(), typename left_type::tag_type());
881 do_divide(e.right(), typename right_type::tag_type());
882 }
883 }
884 template <class Exp>
885 void do_assign(const Exp& e, const detail::modulus&)
886 {
887 //
888 // This operation is only valid for integer backends:
889 //
890 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
891
892 typedef typename Exp::left_type left_type;
893 typedef typename Exp::right_type right_type;
894
895 bool bl = contains_self(e.left());
896 bool br = contains_self(e.right());
897
898 if(bl && is_self(e.left()))
899 {
900 // Ignore the left node, it's *this, just add the right:
901 do_modulus(e.right(), typename right_type::tag_type());
902 }
903 else if(br)
904 {
905 self_type temp(e);
906 temp.m_backend.swap(this->m_backend);
907 }
908 else
909 {
910 do_assign(e.left(), typename left_type::tag_type());
911 do_modulus(e.right(), typename right_type::tag_type());
912 }
913 }
914 template <class Exp>
915 void do_assign(const Exp& e, const detail::modulus_immediates&)
916 {
917 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
918 using default_ops::eval_modulus;
919 eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
920 }
921
922 template <class Exp>
923 void do_assign(const Exp& e, const detail::bitwise_and&)
924 {
925 //
926 // This operation is only valid for integer backends:
927 //
928 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
929
930 typedef typename Exp::left_type left_type;
931 typedef typename Exp::right_type right_type;
932
933 static int const left_depth = left_type::depth;
934 static int const right_depth = right_type::depth;
935
936 bool bl = contains_self(e.left());
937 bool br = contains_self(e.right());
938
939 if(bl && is_self(e.left()))
940 {
941 // Ignore the left node, it's *this, just add the right:
942 do_bitwise_and(e.right(), typename right_type::tag_type());
943 }
944 else if(br && is_self(e.right()))
945 {
946 do_bitwise_and(e.left(), typename left_type::tag_type());
947 }
948 else if(!br && (bl || (left_depth >= right_depth)))
949 {
950 do_assign(e.left(), typename left_type::tag_type());
951 do_bitwise_and(e.right(), typename right_type::tag_type());
952 }
953 else
954 {
955 do_assign(e.right(), typename right_type::tag_type());
956 do_bitwise_and(e.left(), typename left_type::tag_type());
957 }
958 }
959 template <class Exp>
960 void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
961 {
962 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
963 using default_ops::eval_bitwise_and;
964 eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
965 }
966
967 template <class Exp>
968 void do_assign(const Exp& e, const detail::bitwise_or&)
969 {
970 //
971 // This operation is only valid for integer backends:
972 //
973 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
974
975 typedef typename Exp::left_type left_type;
976 typedef typename Exp::right_type right_type;
977
978 static int const left_depth = left_type::depth;
979 static int const right_depth = right_type::depth;
980
981 bool bl = contains_self(e.left());
982 bool br = contains_self(e.right());
983
984 if(bl && is_self(e.left()))
985 {
986 // Ignore the left node, it's *this, just add the right:
987 do_bitwise_or(e.right(), typename right_type::tag_type());
988 }
989 else if(br && is_self(e.right()))
990 {
991 do_bitwise_or(e.left(), typename left_type::tag_type());
992 }
993 else if(!br && (bl || (left_depth >= right_depth)))
994 {
995 do_assign(e.left(), typename left_type::tag_type());
996 do_bitwise_or(e.right(), typename right_type::tag_type());
997 }
998 else
999 {
1000 do_assign(e.right(), typename right_type::tag_type());
1001 do_bitwise_or(e.left(), typename left_type::tag_type());
1002 }
1003 }
1004 template <class Exp>
1005 void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
1006 {
1007 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1008 using default_ops::eval_bitwise_or;
1009 eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1010 }
1011
1012 template <class Exp>
1013 void do_assign(const Exp& e, const detail::bitwise_xor&)
1014 {
1015 //
1016 // This operation is only valid for integer backends:
1017 //
1018 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1019
1020 typedef typename Exp::left_type left_type;
1021 typedef typename Exp::right_type right_type;
1022
1023 static int const left_depth = left_type::depth;
1024 static int const right_depth = right_type::depth;
1025
1026 bool bl = contains_self(e.left());
1027 bool br = contains_self(e.right());
1028
1029 if(bl && is_self(e.left()))
1030 {
1031 // Ignore the left node, it's *this, just add the right:
1032 do_bitwise_xor(e.right(), typename right_type::tag_type());
1033 }
1034 else if(br && is_self(e.right()))
1035 {
1036 do_bitwise_xor(e.left(), typename left_type::tag_type());
1037 }
1038 else if(!br && (bl || (left_depth >= right_depth)))
1039 {
1040 do_assign(e.left(), typename left_type::tag_type());
1041 do_bitwise_xor(e.right(), typename right_type::tag_type());
1042 }
1043 else
1044 {
1045 do_assign(e.right(), typename right_type::tag_type());
1046 do_bitwise_xor(e.left(), typename left_type::tag_type());
1047 }
1048 }
1049 template <class Exp>
1050 void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
1051 {
1052 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1053 using default_ops::eval_bitwise_xor;
1054 eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1055 }
1056 template <class Exp>
1057 void do_assign(const Exp& e, const detail::terminal&)
1058 {
1059 if(!is_self(e))
1060 {
1061 m_backend = canonical_value(e.value());
1062 }
1063 }
1064 template <class Exp>
1065 void do_assign(const Exp& e, const detail::function&)
1066 {
1067 typedef typename Exp::arity tag_type;
1068 do_assign_function(e, tag_type());
1069 }
1070 template <class Exp>
1071 void do_assign(const Exp& e, const detail::shift_left&)
1072 {
1073 // We can only shift by an integer value, not an arbitrary expression:
1074 typedef typename Exp::left_type left_type;
1075 typedef typename Exp::right_type right_type;
1076 typedef typename right_type::arity right_arity;
1077 BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
1078 typedef typename right_type::result_type right_value_type;
1079 BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
1080 typedef typename left_type::tag_type tag_type;
1081 do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type());
1082 }
1083
1084 template <class Exp>
1085 void do_assign(const Exp& e, const detail::shift_right&)
1086 {
1087 // We can only shift by an integer value, not an arbitrary expression:
1088 typedef typename Exp::left_type left_type;
1089 typedef typename Exp::right_type right_type;
1090 typedef typename right_type::arity right_arity;
1091 BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
1092 typedef typename right_type::result_type right_value_type;
1093 BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
1094 typedef typename left_type::tag_type tag_type;
1095 do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type());
1096 }
1097
1098 template <class Exp>
1099 void do_assign(const Exp& e, const detail::bitwise_complement&)
1100 {
1101 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
1102 using default_ops::eval_complement;
1103 self_type temp(e.left());
1104 eval_complement(m_backend, temp.backend());
1105 }
1106
1107 template <class Exp>
1108 void do_assign(const Exp& e, const detail::complement_immediates&)
1109 {
1110 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
1111 using default_ops::eval_complement;
1112 eval_complement(m_backend, canonical_value(e.left().value()));
1113 }
1114
1115 template <class Exp, class Val>
1116 void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
1117 {
1118 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
1119 using default_ops::eval_right_shift;
1120 detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1121 eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
1122 }
1123
1124 template <class Exp, class Val>
1125 void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
1126 {
1127 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
1128 using default_ops::eval_left_shift;
1129 detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1130 eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
1131 }
1132
1133 template <class Exp, class Val, class Tag>
1134 void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
1135 {
1136 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
1137 using default_ops::eval_right_shift;
1138 self_type temp(e);
1139 detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1140 eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
1141 }
1142
1143 template <class Exp, class Val, class Tag>
1144 void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
1145 {
1146 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
1147 using default_ops::eval_left_shift;
1148 self_type temp(e);
1149 detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1150 eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
1151 }
1152
1153 template <class Exp>
1154 void do_assign_function(const Exp& e, const mpl::int_<1>&)
1155 {
1156 e.left().value()(&m_backend);
1157 }
1158 template <class Exp>
1159 void do_assign_function(const Exp& e, const mpl::int_<2>&)
1160 {
1161 typedef typename Exp::right_type right_type;
1162 typedef typename right_type::tag_type tag_type;
1163 do_assign_function_1(e.left().value(), e.right_ref(), tag_type());
1164 }
1165 template <class F, class Exp>
1166 void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
1167 {
1168 f(m_backend, function_arg_value(val));
1169 }
1170 template <class F, class Exp, class Tag>
1171 void do_assign_function_1(const F& f, const Exp& val, const Tag&)
1172 {
1173 number t(val);
1174 f(m_backend, t.backend());
1175 }
1176 template <class Exp>
1177 void do_assign_function(const Exp& e, const mpl::int_<3>&)
1178 {
1179 typedef typename Exp::middle_type middle_type;
1180 typedef typename middle_type::tag_type tag_type;
1181 typedef typename Exp::right_type end_type;
1182 typedef typename end_type::tag_type end_tag;
1183 do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag());
1184 }
1185 template <class F, class Exp1, class Exp2>
1186 void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)
1187 {
1188 f(m_backend, function_arg_value(val1), function_arg_value(val2));
1189 }
1190 template <class F, class Exp1, class Exp2, class Tag1>
1191 void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)
1192 {
1193 self_type temp1(val1);
1194 f(m_backend, BOOST_MP_MOVE(temp1.backend()), function_arg_value(val2));
1195 }
1196 template <class F, class Exp1, class Exp2, class Tag2>
1197 void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)
1198 {
1199 self_type temp2(val2);
1200 f(m_backend, function_arg_value(val1), BOOST_MP_MOVE(temp2.backend()));
1201 }
1202 template <class F, class Exp1, class Exp2, class Tag1, class Tag2>
1203 void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)
1204 {
1205 self_type temp1(val1);
1206 self_type temp2(val2);
1207 f(m_backend, BOOST_MP_MOVE(temp1.backend()), BOOST_MP_MOVE(temp2.backend()));
1208 }
1209
1210 template <class Exp>
1211 void do_assign_function(const Exp& e, const mpl::int_<4>&)
1212 {
1213 typedef typename Exp::left_middle_type left_type;
1214 typedef typename left_type::tag_type left_tag_type;
1215 typedef typename Exp::right_middle_type middle_type;
1216 typedef typename middle_type::tag_type middle_tag_type;
1217 typedef typename Exp::right_type right_type;
1218 typedef typename right_type::tag_type right_tag_type;
1219 do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type());
1220 }
1221 template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
1222 void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)
1223 {
1224 do_assign_function_3b(f, val1, val2, val3, t2, t3);
1225 }
1226 template <class F, class Exp1, class Exp2, class Exp3, class Tag1, class Tag2, class Tag3>
1227 void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)
1228 {
1229 number t(val1);
1230 do_assign_function_3b(f, BOOST_MP_MOVE(t), val2, val3, t2, t3);
1231 }
1232 template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
1233 void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)
1234 {
1235 do_assign_function_3c(f, val1, val2, val3, t3);
1236 }
1237 template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
1238 void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3)
1239 {
1240 number t(val2);
1241 do_assign_function_3c(f, val1, BOOST_MP_MOVE(t), val3, t3);
1242 }
1243 template <class F, class Exp1, class Exp2, class Exp3>
1244 void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)
1245 {
1246 f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));
1247 }
1248 template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
1249 void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/)
1250 {
1251 number t(val3);
1252 do_assign_function_3c(f, val1, val2, BOOST_MP_MOVE(t), detail::terminal());
1253 }
1254
1255 template <class Exp>
1256 void do_add(const Exp& e, const detail::terminal&)
1257 {
1258 using default_ops::eval_add;
1259 eval_add(m_backend, canonical_value(e.value()));
1260 }
1261
1262 template <class Exp>
1263 void do_add(const Exp& e, const detail::negate&)
1264 {
1265 typedef typename Exp::left_type left_type;
1266 do_subtract(e.left(), typename left_type::tag_type());
1267 }
1268
1269 template <class Exp>
1270 void do_add(const Exp& e, const detail::plus&)
1271 {
1272 typedef typename Exp::left_type left_type;
1273 typedef typename Exp::right_type right_type;
1274 do_add(e.left(), typename left_type::tag_type());
1275 do_add(e.right(), typename right_type::tag_type());
1276 }
1277
1278 template <class Exp>
1279 void do_add(const Exp& e, const detail::minus&)
1280 {
1281 typedef typename Exp::left_type left_type;
1282 typedef typename Exp::right_type right_type;
1283 do_add(e.left(), typename left_type::tag_type());
1284 do_subtract(e.right(), typename right_type::tag_type());
1285 }
1286
1287 template <class Exp, class unknown>
1288 void do_add(const Exp& e, const unknown&)
1289 {
1290 self_type temp(e);
1291 do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1292 }
1293
1294 template <class Exp>
1295 void do_add(const Exp& e, const detail::add_immediates&)
1296 {
1297 using default_ops::eval_add;
1298 eval_add(m_backend, canonical_value(e.left().value()));
1299 eval_add(m_backend, canonical_value(e.right().value()));
1300 }
1301 template <class Exp>
1302 void do_add(const Exp& e, const detail::subtract_immediates&)
1303 {
1304 using default_ops::eval_add;
1305 using default_ops::eval_subtract;
1306 eval_add(m_backend, canonical_value(e.left().value()));
1307 eval_subtract(m_backend, canonical_value(e.right().value()));
1308 }
1309 template <class Exp>
1310 void do_subtract(const Exp& e, const detail::terminal&)
1311 {
1312 using default_ops::eval_subtract;
1313 eval_subtract(m_backend, canonical_value(e.value()));
1314 }
1315
1316 template <class Exp>
1317 void do_subtract(const Exp& e, const detail::negate&)
1318 {
1319 typedef typename Exp::left_type left_type;
1320 do_add(e.left(), typename left_type::tag_type());
1321 }
1322
1323 template <class Exp>
1324 void do_subtract(const Exp& e, const detail::plus&)
1325 {
1326 typedef typename Exp::left_type left_type;
1327 typedef typename Exp::right_type right_type;
1328 do_subtract(e.left(), typename left_type::tag_type());
1329 do_subtract(e.right(), typename right_type::tag_type());
1330 }
1331
1332 template <class Exp>
1333 void do_subtract(const Exp& e, const detail::minus&)
1334 {
1335 typedef typename Exp::left_type left_type;
1336 typedef typename Exp::right_type right_type;
1337 do_subtract(e.left(), typename left_type::tag_type());
1338 do_add(e.right(), typename right_type::tag_type());
1339 }
1340 template <class Exp>
1341 void do_subtract(const Exp& e, const detail::add_immediates&)
1342 {
1343 using default_ops::eval_subtract;
1344 eval_subtract(m_backend, canonical_value(e.left().value()));
1345 eval_subtract(m_backend, canonical_value(e.right().value()));
1346 }
1347 template <class Exp>
1348 void do_subtract(const Exp& e, const detail::subtract_immediates&)
1349 {
1350 using default_ops::eval_add;
1351 using default_ops::eval_subtract;
1352 eval_subtract(m_backend, canonical_value(e.left().value()));
1353 eval_add(m_backend, canonical_value(e.right().value()));
1354 }
1355 template <class Exp, class unknown>
1356 void do_subtract(const Exp& e, const unknown&)
1357 {
1358 self_type temp(e);
1359 do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1360 }
1361
1362 template <class Exp>
1363 void do_multiplies(const Exp& e, const detail::terminal&)
1364 {
1365 using default_ops::eval_multiply;
1366 eval_multiply(m_backend, canonical_value(e.value()));
1367 }
1368
1369 template <class Exp>
1370 void do_multiplies(const Exp& e, const detail::negate&)
1371 {
1372 typedef typename Exp::left_type left_type;
1373 do_multiplies(e.left(), typename left_type::tag_type());
1374 m_backend.negate();
1375 }
1376
1377 template <class Exp>
1378 void do_multiplies(const Exp& e, const detail::multiplies&)
1379 {
1380 typedef typename Exp::left_type left_type;
1381 typedef typename Exp::right_type right_type;
1382 do_multiplies(e.left(), typename left_type::tag_type());
1383 do_multiplies(e.right(), typename right_type::tag_type());
1384 }
1385
1386 template <class Exp>
1387 void do_multiplies(const Exp& e, const detail::divides&)
1388 {
1389 typedef typename Exp::left_type left_type;
1390 typedef typename Exp::right_type right_type;
1391 do_multiplies(e.left(), typename left_type::tag_type());
1392 do_divide(e.right(), typename right_type::tag_type());
1393 }
1394
1395 template <class Exp>
1396 void do_multiplies(const Exp& e, const detail::multiply_immediates&)
1397 {
1398 using default_ops::eval_multiply;
1399 eval_multiply(m_backend, canonical_value(e.left().value()));
1400 eval_multiply(m_backend, canonical_value(e.right().value()));
1401 }
1402 template <class Exp>
1403 void do_multiplies(const Exp& e, const detail::divide_immediates&)
1404 {
1405 using default_ops::eval_multiply;
1406 using default_ops::eval_divide;
1407 eval_multiply(m_backend, canonical_value(e.left().value()));
1408 eval_divide(m_backend, canonical_value(e.right().value()));
1409 }
1410 template <class Exp, class unknown>
1411 void do_multiplies(const Exp& e, const unknown&)
1412 {
1413 using default_ops::eval_multiply;
1414 self_type temp(e);
1415 eval_multiply(m_backend, temp.m_backend);
1416 }
1417
1418 template <class Exp>
1419 void do_divide(const Exp& e, const detail::terminal&)
1420 {
1421 using default_ops::eval_divide;
1422 eval_divide(m_backend, canonical_value(e.value()));
1423 }
1424
1425 template <class Exp>
1426 void do_divide(const Exp& e, const detail::negate&)
1427 {
1428 typedef typename Exp::left_type left_type;
1429 do_divide(e.left(), typename left_type::tag_type());
1430 m_backend.negate();
1431 }
1432
1433 template <class Exp>
1434 void do_divide(const Exp& e, const detail::multiplies&)
1435 {
1436 typedef typename Exp::left_type left_type;
1437 typedef typename Exp::right_type right_type;
1438 do_divide(e.left(), typename left_type::tag_type());
1439 do_divide(e.right(), typename right_type::tag_type());
1440 }
1441
1442 template <class Exp>
1443 void do_divide(const Exp& e, const detail::divides&)
1444 {
1445 typedef typename Exp::left_type left_type;
1446 typedef typename Exp::right_type right_type;
1447 do_divide(e.left(), typename left_type::tag_type());
1448 do_multiplies(e.right(), typename right_type::tag_type());
1449 }
1450
1451 template <class Exp>
1452 void do_divides(const Exp& e, const detail::multiply_immediates&)
1453 {
1454 using default_ops::eval_divide;
1455 eval_divide(m_backend, canonical_value(e.left().value()));
1456 eval_divide(m_backend, canonical_value(e.right().value()));
1457 }
1458 template <class Exp>
1459 void do_divides(const Exp& e, const detail::divide_immediates&)
1460 {
1461 using default_ops::eval_multiply;
1462 using default_ops::eval_divide;
1463 eval_divide(m_backend, canonical_value(e.left().value()));
1464 mutiply(m_backend, canonical_value(e.right().value()));
1465 }
1466
1467 template <class Exp, class unknown>
1468 void do_divide(const Exp& e, const unknown&)
1469 {
1470 using default_ops::eval_multiply;
1471 self_type temp(e);
1472 eval_divide(m_backend, temp.m_backend);
1473 }
1474
1475 template <class Exp>
1476 void do_modulus(const Exp& e, const detail::terminal&)
1477 {
1478 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
1479 using default_ops::eval_modulus;
1480 eval_modulus(m_backend, canonical_value(e.value()));
1481 }
1482
1483 template <class Exp, class Unknown>
1484 void do_modulus(const Exp& e, const Unknown&)
1485 {
1486 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
1487 using default_ops::eval_modulus;
1488 self_type temp(e);
1489 eval_modulus(m_backend, canonical_value(temp));
1490 }
1491
1492 template <class Exp>
1493 void do_bitwise_and(const Exp& e, const detail::terminal&)
1494 {
1495 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
1496 using default_ops::eval_bitwise_and;
1497 eval_bitwise_and(m_backend, canonical_value(e.value()));
1498 }
1499 template <class Exp>
1500 void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
1501 {
1502 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
1503 typedef typename Exp::left_type left_type;
1504 typedef typename Exp::right_type right_type;
1505 do_bitwise_and(e.left(), typename left_type::tag_type());
1506 do_bitwise_and(e.right(), typename right_type::tag_type());
1507 }
1508 template <class Exp, class unknown>
1509 void do_bitwise_and(const Exp& e, const unknown&)
1510 {
1511 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
1512 using default_ops::eval_bitwise_and;
1513 self_type temp(e);
1514 eval_bitwise_and(m_backend, temp.m_backend);
1515 }
1516
1517 template <class Exp>
1518 void do_bitwise_or(const Exp& e, const detail::terminal&)
1519 {
1520 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
1521 using default_ops::eval_bitwise_or;
1522 eval_bitwise_or(m_backend, canonical_value(e.value()));
1523 }
1524 template <class Exp>
1525 void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
1526 {
1527 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
1528 typedef typename Exp::left_type left_type;
1529 typedef typename Exp::right_type right_type;
1530 do_bitwise_or(e.left(), typename left_type::tag_type());
1531 do_bitwise_or(e.right(), typename right_type::tag_type());
1532 }
1533 template <class Exp, class unknown>
1534 void do_bitwise_or(const Exp& e, const unknown&)
1535 {
1536 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
1537 using default_ops::eval_bitwise_or;
1538 self_type temp(e);
1539 eval_bitwise_or(m_backend, temp.m_backend);
1540 }
1541
1542 template <class Exp>
1543 void do_bitwise_xor(const Exp& e, const detail::terminal&)
1544 {
1545 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
1546 using default_ops::eval_bitwise_xor;
1547 eval_bitwise_xor(m_backend, canonical_value(e.value()));
1548 }
1549 template <class Exp>
1550 void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
1551 {
1552 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
1553 typedef typename Exp::left_type left_type;
1554 typedef typename Exp::right_type right_type;
1555 do_bitwise_xor(e.left(), typename left_type::tag_type());
1556 do_bitwise_xor(e.right(), typename right_type::tag_type());
1557 }
1558 template <class Exp, class unknown>
1559 void do_bitwise_xor(const Exp& e, const unknown&)
1560 {
1561 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
1562 using default_ops::eval_bitwise_xor;
1563 self_type temp(e);
1564 eval_bitwise_xor(m_backend, temp.m_backend);
1565 }
1566
1567 // Tests if the expression contains a reference to *this:
1568 template <class Exp>
1569 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e)const BOOST_NOEXCEPT
1570 {
1571 return contains_self(e, typename Exp::arity());
1572 }
1573 template <class Exp>
1574 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
1575 {
1576 return is_realy_self(e.value());
1577 }
1578 template <class Exp>
1579 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<1> const&)const BOOST_NOEXCEPT
1580 {
1581 typedef typename Exp::left_type child_type;
1582 return contains_self(e.left(), typename child_type::arity());
1583 }
1584 template <class Exp>
1585 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<2> const&)const BOOST_NOEXCEPT
1586 {
1587 typedef typename Exp::left_type child0_type;
1588 typedef typename Exp::right_type child1_type;
1589 return contains_self(e.left(), typename child0_type::arity())
1590 || contains_self(e.right(), typename child1_type::arity());
1591 }
1592 template <class Exp>
1593 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<3> const&)const BOOST_NOEXCEPT
1594 {
1595 typedef typename Exp::left_type child0_type;
1596 typedef typename Exp::middle_type child1_type;
1597 typedef typename Exp::right_type child2_type;
1598 return contains_self(e.left(), typename child0_type::arity())
1599 || contains_self(e.middle(), typename child1_type::arity())
1600 || contains_self(e.right(), typename child2_type::arity());
1601 }
1602
1603 // Test if the expression is a reference to *this:
1604 template <class Exp>
1605 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e)const BOOST_NOEXCEPT
1606 {
1607 return is_self(e, typename Exp::arity());
1608 }
1609 template <class Exp>
1610 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
1611 {
1612 return is_realy_self(e.value());
1613 }
1614 template <class Exp, int v>
1615 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp&, mpl::int_<v> const&)const BOOST_NOEXCEPT
1616 {
1617 return false;
1618 }
1619
1620 template <class Val>
1621 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const Val&)const BOOST_NOEXCEPT{ return false; }
1622 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const self_type& v)const BOOST_NOEXCEPT{ return &v == this; }
1623
1624 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); }
1625 template <class V>
1626 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; }
1627 template <class A1, class A2, class A3, class A4>
1628 static BOOST_MP_FORCEINLINE const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value(); }
1629 template <class A2, class A3, class A4>
1630 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); }
1631 Backend m_backend;
1632
1633 public:
1634 //
1635 // These shouldn't really need to be public, or even member functions, but it makes implementing
1636 // the non-member operators way easier if they are:
1637 //
1638 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& canonical_value(const self_type& v) BOOST_NOEXCEPT { return v.m_backend; }
1639 template <class B2, expression_template_option ET>
1640 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const B2& canonical_value(const number<B2, ET>& v) BOOST_NOEXCEPT { return v.backend(); }
1641 template <class V>
1642 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::disable_if<is_same<typename detail::canonical<V, Backend>::type, V>, typename detail::canonical<V, Backend>::type>::type
1643 canonical_value(const V& v) BOOST_NOEXCEPT { return static_cast<typename detail::canonical<V, Backend>::type>(v); }
1644 template <class V>
1645 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::enable_if<is_same<typename detail::canonical<V, Backend>::type, V>, const V&>::type
1646 canonical_value(const V& v) BOOST_NOEXCEPT { return v; }
1647 static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) BOOST_NOEXCEPT { return v.c_str(); }
1648
1649 };
1650
1651 template <class Backend, expression_template_option ExpressionTemplates>
1652 inline std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r)
1653 {
1654 std::streamsize d = os.precision();
1655 std::string s = r.str(d, os.flags());
1656 std::streamsize ss = os.width();
1657 if(ss > static_cast<std::streamsize>(s.size()))
1658 {
1659 char fill = os.fill();
1660 if((os.flags() & std::ios_base::left) == std::ios_base::left)
1661 s.append(static_cast<std::string::size_type>(ss - s.size()), fill);
1662 else
1663 s.insert(0, static_cast<std::string::size_type>(ss - s.size()), fill);
1664 }
1665 return os << s;
1666 }
1667
1668 namespace detail{
1669
1670 template <class tag, class A1, class A2, class A3, class A4>
1671 inline std::ostream& operator << (std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
1672 {
1673 typedef typename expression<tag, A1, A2, A3, A4>::result_type value_type;
1674 value_type temp(r);
1675 return os << temp;
1676 }
1677
1678 } // namespace detail
1679
1680 template <class Backend, expression_template_option ExpressionTemplates>
1681 inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r)
1682 {
1683 bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
1684 bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
1685 std::string s;
1686 is >> s;
1687 if(hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))
1688 s.insert(s.find_first_not_of("+-"), "0x");
1689 if(oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))
1690 s.insert(s.find_first_not_of("+-"), "0");
1691 r.assign(s);
1692 return is;
1693 }
1694
1695 template <class Backend, expression_template_option ExpressionTemplates>
1696 BOOST_MP_FORCEINLINE void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b)
1697 {
1698 a.swap(b);
1699 }
1700
1701 } // namespace multiprecision
1702
1703 template <class T>
1704 class rational;
1705
1706 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1707 inline std::istream& operator >> (std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
1708 {
1709 std::string s1;
1710 multiprecision::number<Backend, ExpressionTemplates> v1, v2;
1711 char c;
1712 bool have_hex = false;
1713 bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
1714 bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
1715
1716 while((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
1717 {
1718 if(c == 'x' || c == 'X')
1719 have_hex = true;
1720 s1.append(1, c);
1721 is.get();
1722 }
1723 if(hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
1724 s1.insert(0, "0x");
1725 if(oct_format && (s1[0] != '0'))
1726 s1.insert(0, "0");
1727 v1.assign(s1);
1728 s1.erase();
1729 if(c == '/')
1730 {
1731 is.get();
1732 while((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
1733 {
1734 if(c == 'x' || c == 'X')
1735 have_hex = true;
1736 s1.append(1, c);
1737 is.get();
1738 }
1739 if(hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
1740 s1.insert(0, "0x");
1741 if(oct_format && (s1[0] != '0'))
1742 s1.insert(0, "0");
1743 v2.assign(s1);
1744 }
1745 else
1746 v2 = 1;
1747 r.assign(v1, v2);
1748 return is;
1749 }
1750
1751 template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
1752 typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator == (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
1753 {
1754 return a == multiprecision::number<T, ExpressionTemplates>(b);
1755 }
1756
1757 template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
1758 typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator == (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1759 {
1760 return a == multiprecision::number<T, ExpressionTemplates>(b);
1761 }
1762
1763 template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
1764 typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator != (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
1765 {
1766 return a != multiprecision::number<T, ExpressionTemplates>(b);
1767 }
1768
1769 template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
1770 typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator != (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1771 {
1772 return a != multiprecision::number<T, ExpressionTemplates>(b);
1773 }
1774
1775 template <class T, multiprecision::expression_template_option ExpressionTemplates>
1776 inline multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1777 {
1778 return a.numerator();
1779 }
1780
1781 template <class T, multiprecision::expression_template_option ExpressionTemplates>
1782 inline multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1783 {
1784 return a.denominator();
1785 }
1786
1787 #ifdef BOOST_MSVC
1788 #pragma warning(pop)
1789 #endif
1790
1791 } // namespaces
1792
1793 #include <boost/multiprecision/detail/ublas_interop.hpp>
1794
1795 #endif