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

source code of boost/boost/multiprecision/number.hpp