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