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)
6 #ifndef BOOST_MATH_EXTENDED_REAL_HPP
7 #define BOOST_MATH_EXTENDED_REAL_HPP
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
29 namespace boost{ namespace multiprecision{
32 // warning C4127: conditional expression is constant
33 // warning C4714: function marked as __forceinline not inlined
35 #pragma warning(disable:4127 4714 6326)
38 template <class Backend, expression_template_option ExpressionTemplates>
41 typedef number<Backend, ExpressionTemplates> self_type;
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){}
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
53 m_backend = canonical_value(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
61 BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
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){}
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
73 BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
75 m_backend = canonical_value(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)
83 BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
84 : m_backend(canonical_value(v)) {}
87 // This conflicts with component based initialization (for rational and complex types)
88 // which is arguably more useful. Disabled for now.
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)
93 m_backend.precision(digits10);
94 m_backend = canonical_value(v);
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()) {}
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()) {}
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)
113 // Attempt a generic interconvertion:
115 using detail::generic_interconvert;
116 generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
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()) {}
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)
128 using default_ops::assign_components;
129 assign_components(m_backend, canonical_value(v1), canonical_value(v2));
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)
134 using default_ops::assign_components;
135 assign_components(m_backend, v1.backend(), v2.backend());
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)
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());
145 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
146 number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
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());
153 BOOST_MP_FORCEINLINE number& operator=(const number& e)
154 BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<Backend const&>()))
156 m_backend = e.m_backend;
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&>()))
165 m_backend = canonical_value(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&>()))
172 m_backend = canonical_value(v);
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)
180 // Attempt a generic interconvertion:
182 using detail::generic_interconvert;
183 generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
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)
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)
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>()))
206 m_backend = static_cast<Backend&&>(r.m_backend);
211 number& operator+=(const self_type& val)
213 do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
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)
220 // Create a copy if e contains this, but not if we're just doing a
222 if(contains_self(e) && !is_self(e))
225 do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
234 template <class Arg1, class Arg2, class Arg3, class Arg4>
235 number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
238 // Fused multiply-add:
240 using default_ops::eval_multiply_add;
241 eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
246 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
247 operator+=(const V& v)
249 using default_ops::eval_add;
250 eval_add(m_backend, canonical_value(v));
254 number& operator-=(const self_type& val)
256 do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
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)
263 // Create a copy if e contains this:
267 do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
271 do_subtract(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
277 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
278 operator-=(const V& v)
280 using default_ops::eval_subtract;
281 eval_subtract(m_backend, canonical_value(v));
285 template <class Arg1, class Arg2, class Arg3, class Arg4>
286 number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
289 // Fused multiply-subtract:
291 using default_ops::eval_multiply_subtract;
292 eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
297 number& operator *= (const self_type& e)
299 do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
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)
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))
311 do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
315 do_multiplies(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
321 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
322 operator*=(const V& v)
324 using default_ops::eval_multiply;
325 eval_multiply(m_backend, canonical_value(v));
329 number& operator%=(const self_type& e)
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());
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)
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:
343 do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
347 do_modulus(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
352 typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
353 operator%=(const V& v)
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));
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...
369 BOOST_MP_FORCEINLINE number& operator++()
371 using default_ops::eval_increment;
372 eval_increment(m_backend);
376 BOOST_MP_FORCEINLINE number& operator--()
378 using default_ops::eval_decrement;
379 eval_decrement(m_backend);
383 inline number operator++(int)
385 using default_ops::eval_increment;
386 self_type temp(*this);
387 eval_increment(m_backend);
388 return BOOST_MP_MOVE(temp);
391 inline number operator--(int)
393 using default_ops::eval_decrement;
394 self_type temp(*this);
395 eval_decrement(m_backend);
396 return BOOST_MP_MOVE(temp);
400 BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator <<= (V val)
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)));
409 BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator >>= (V val)
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)));
417 BOOST_MP_FORCEINLINE number& operator /= (const self_type& e)
419 do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
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)
426 // Create a temporary if the RHS references *this:
430 do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
434 do_divide(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
440 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
441 operator/=(const V& v)
443 using default_ops::eval_divide;
444 eval_divide(m_backend, canonical_value(v));
448 BOOST_MP_FORCEINLINE number& operator&=(const self_type& e)
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());
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)
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))
464 do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
468 do_bitwise_and(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
474 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
475 operator&=(const V& v)
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));
483 BOOST_MP_FORCEINLINE number& operator|=(const self_type& e)
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());
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)
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))
499 do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
503 do_bitwise_or(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
509 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
510 operator|=(const V& v)
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));
518 BOOST_MP_FORCEINLINE number& operator^=(const self_type& e)
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());
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)
528 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
532 do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
536 do_bitwise_xor(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
542 BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
543 operator^=(const V& v)
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));
553 BOOST_MP_FORCEINLINE void swap(self_type& other) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))
555 m_backend.swap(other.backend());
560 BOOST_MP_FORCEINLINE bool is_zero()const
562 using default_ops::eval_is_zero;
563 return eval_is_zero(m_backend);
565 BOOST_MP_FORCEINLINE int sign()const
567 using default_ops::eval_get_sign;
568 return eval_get_sign(m_backend);
571 // String conversion functions:
573 std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0))const
575 return m_backend.str(digits, f);
577 template<class Archive>
578 void serialize(Archive & ar, const unsigned int /*version*/)
584 void convert_to_imp(T* result)const
586 using default_ops::eval_convert_to;
587 eval_convert_to(result, m_backend);
589 template <class B2, expression_template_option ET>
590 void convert_to_imp(number<B2, ET>* result)const
592 result->assign(*this);
594 void convert_to_imp(std::string* result)const
596 *result = this->str();
603 convert_to_imp(&result);
607 // Use in boolean context, and explicit conversion operators:
609 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
610 # if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
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:
616 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
617 explicit operator T ()const
619 using default_ops::eval_is_zero;
620 return !eval_is_zero(backend());
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
625 return this->template convert_to<T>();
629 explicit operator T()const
631 return this->template convert_to<T>();
633 BOOST_MP_FORCEINLINE explicit operator bool()const
637 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
638 BOOST_MP_FORCEINLINE explicit operator void()const {}
642 typedef bool (self_type::*unmentionable_type)()const;
644 BOOST_MP_FORCEINLINE operator unmentionable_type()const
646 return is_zero() ? 0 : &self_type::is_zero;
650 // Default precision:
652 static unsigned default_precision() BOOST_NOEXCEPT
654 return Backend::default_precision();
656 static void default_precision(unsigned digits10)
658 Backend::default_precision(digits10);
660 unsigned precision()const BOOST_NOEXCEPT
662 return m_backend.precision();
664 void precision(unsigned digits10)
666 m_backend.precision(digits10);
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>())))
674 return m_backend.compare(o.m_backend);
677 BOOST_MP_FORCEINLINE typename boost::enable_if<is_arithmetic<V>, int>::type compare(const V& o)const
679 using default_ops::eval_get_sign;
681 return eval_get_sign(m_backend);
682 return m_backend.compare(canonical_value(o));
684 BOOST_MP_FORCEINLINE Backend& backend() BOOST_NOEXCEPT
688 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& backend()const BOOST_NOEXCEPT
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_&)
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_&)
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;
710 void do_assign(const Exp& e, const detail::add_immediates&)
712 using default_ops::eval_add;
713 eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
716 void do_assign(const Exp& e, const detail::subtract_immediates&)
718 using default_ops::eval_subtract;
719 eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
722 void do_assign(const Exp& e, const detail::multiply_immediates&)
724 using default_ops::eval_multiply;
725 eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
728 void do_assign(const Exp& e, const detail::multiply_add&)
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()));
734 void do_assign(const Exp& e, const detail::multiply_subtract&)
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()));
741 void do_assign(const Exp& e, const detail::divide_immediates&)
743 using default_ops::eval_divide;
744 eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
748 void do_assign(const Exp& e, const detail::negate&)
750 typedef typename Exp::left_type left_type;
751 do_assign(e.left(), typename left_type::tag_type());
755 void do_assign(const Exp& e, const detail::plus&)
757 typedef typename Exp::left_type left_type;
758 typedef typename Exp::right_type right_type;
760 static int const left_depth = left_type::depth;
761 static int const right_depth = right_type::depth;
763 bool bl = contains_self(e.left());
764 bool br = contains_self(e.right());
769 temp.m_backend.swap(this->m_backend);
771 else if(bl && is_self(e.left()))
773 // Ignore the left node, it's *this, just add the right:
774 do_add(e.right(), typename right_type::tag_type());
776 else if(br && is_self(e.right()))
778 // Ignore the right node, it's *this, just add the left:
779 do_add(e.left(), typename left_type::tag_type());
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());
788 do_assign(e.right(), typename right_type::tag_type());
789 do_add(e.left(), typename left_type::tag_type());
793 void do_assign(const Exp& e, const detail::minus&)
795 typedef typename Exp::left_type left_type;
796 typedef typename Exp::right_type right_type;
798 static int const left_depth = left_type::depth;
799 static int const right_depth = right_type::depth;
801 bool bl = contains_self(e.left());
802 bool br = contains_self(e.right());
807 temp.m_backend.swap(this->m_backend);
809 else if(bl && is_self(e.left()))
811 // Ignore the left node, it's *this, just subtract the right:
812 do_subtract(e.right(), typename right_type::tag_type());
814 else if(br && is_self(e.right()))
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());
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());
827 do_assign(e.right(), typename right_type::tag_type());
828 do_subtract(e.left(), typename left_type::tag_type());
833 void do_assign(const Exp& e, const detail::multiplies&)
835 typedef typename Exp::left_type left_type;
836 typedef typename Exp::right_type right_type;
838 static int const left_depth = left_type::depth;
839 static int const right_depth = right_type::depth;
841 bool bl = contains_self(e.left());
842 bool br = contains_self(e.right());
847 temp.m_backend.swap(this->m_backend);
849 else if(bl && is_self(e.left()))
851 // Ignore the left node, it's *this, just add the right:
852 do_multiplies(e.right(), typename right_type::tag_type());
854 else if(br && is_self(e.right()))
856 // Ignore the right node, it's *this, just add the left:
857 do_multiplies(e.left(), typename left_type::tag_type());
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());
866 do_assign(e.right(), typename right_type::tag_type());
867 do_multiplies(e.left(), typename left_type::tag_type());
871 void do_assign(const Exp& e, const detail::divides&)
873 typedef typename Exp::left_type left_type;
874 typedef typename Exp::right_type right_type;
876 bool bl = contains_self(e.left());
877 bool br = contains_self(e.right());
879 if(bl && is_self(e.left()))
881 // Ignore the left node, it's *this, just add the right:
882 do_divide(e.right(), typename right_type::tag_type());
887 temp.m_backend.swap(this->m_backend);
891 do_assign(e.left(), typename left_type::tag_type());
892 do_divide(e.right(), typename right_type::tag_type());
896 void do_assign(const Exp& e, const detail::modulus&)
899 // This operation is only valid for integer backends:
901 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
903 typedef typename Exp::left_type left_type;
904 typedef typename Exp::right_type right_type;
906 bool bl = contains_self(e.left());
907 bool br = contains_self(e.right());
909 if(bl && is_self(e.left()))
911 // Ignore the left node, it's *this, just add the right:
912 do_modulus(e.right(), typename right_type::tag_type());
917 temp.m_backend.swap(this->m_backend);
921 do_assign(e.left(), typename left_type::tag_type());
922 do_modulus(e.right(), typename right_type::tag_type());
926 void do_assign(const Exp& e, const detail::modulus_immediates&)
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()));
934 void do_assign(const Exp& e, const detail::bitwise_and&)
937 // This operation is only valid for integer backends:
939 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
941 typedef typename Exp::left_type left_type;
942 typedef typename Exp::right_type right_type;
944 static int const left_depth = left_type::depth;
945 static int const right_depth = right_type::depth;
947 bool bl = contains_self(e.left());
948 bool br = contains_self(e.right());
950 if(bl && is_self(e.left()))
952 // Ignore the left node, it's *this, just add the right:
953 do_bitwise_and(e.right(), typename right_type::tag_type());
955 else if(br && is_self(e.right()))
957 do_bitwise_and(e.left(), typename left_type::tag_type());
959 else if(!br && (bl || (left_depth >= right_depth)))
961 do_assign(e.left(), typename left_type::tag_type());
962 do_bitwise_and(e.right(), typename right_type::tag_type());
966 do_assign(e.right(), typename right_type::tag_type());
967 do_bitwise_and(e.left(), typename left_type::tag_type());
971 void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
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()));
979 void do_assign(const Exp& e, const detail::bitwise_or&)
982 // This operation is only valid for integer backends:
984 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
986 typedef typename Exp::left_type left_type;
987 typedef typename Exp::right_type right_type;
989 static int const left_depth = left_type::depth;
990 static int const right_depth = right_type::depth;
992 bool bl = contains_self(e.left());
993 bool br = contains_self(e.right());
995 if(bl && is_self(e.left()))
997 // Ignore the left node, it's *this, just add the right:
998 do_bitwise_or(e.right(), typename right_type::tag_type());
1000 else if(br && is_self(e.right()))
1002 do_bitwise_or(e.left(), typename left_type::tag_type());
1004 else if(!br && (bl || (left_depth >= right_depth)))
1006 do_assign(e.left(), typename left_type::tag_type());
1007 do_bitwise_or(e.right(), typename right_type::tag_type());
1011 do_assign(e.right(), typename right_type::tag_type());
1012 do_bitwise_or(e.left(), typename left_type::tag_type());
1015 template <class Exp>
1016 void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
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()));
1023 template <class Exp>
1024 void do_assign(const Exp& e, const detail::bitwise_xor&)
1027 // This operation is only valid for integer backends:
1029 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1031 typedef typename Exp::left_type left_type;
1032 typedef typename Exp::right_type right_type;
1034 static int const left_depth = left_type::depth;
1035 static int const right_depth = right_type::depth;
1037 bool bl = contains_self(e.left());
1038 bool br = contains_self(e.right());
1040 if(bl && is_self(e.left()))
1042 // Ignore the left node, it's *this, just add the right:
1043 do_bitwise_xor(e.right(), typename right_type::tag_type());
1045 else if(br && is_self(e.right()))
1047 do_bitwise_xor(e.left(), typename left_type::tag_type());
1049 else if(!br && (bl || (left_depth >= right_depth)))
1051 do_assign(e.left(), typename left_type::tag_type());
1052 do_bitwise_xor(e.right(), typename right_type::tag_type());
1056 do_assign(e.right(), typename right_type::tag_type());
1057 do_bitwise_xor(e.left(), typename left_type::tag_type());
1060 template <class Exp>
1061 void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
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()));
1067 template <class Exp>
1068 void do_assign(const Exp& e, const detail::terminal&)
1072 m_backend = canonical_value(e.value());
1075 template <class Exp>
1076 void do_assign(const Exp& e, const detail::function&)
1078 typedef typename Exp::arity tag_type;
1079 do_assign_function(e, tag_type());
1081 template <class Exp>
1082 void do_assign(const Exp& e, const detail::shift_left&)
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());
1095 template <class Exp>
1096 void do_assign(const Exp& e, const detail::shift_right&)
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());
1109 template <class Exp>
1110 void do_assign(const Exp& e, const detail::bitwise_complement&)
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());
1118 template <class Exp>
1119 void do_assign(const Exp& e, const detail::complement_immediates&)
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()));
1126 template <class Exp, class Val>
1127 void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
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));
1135 template <class Exp, class Val>
1136 void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
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));
1144 template <class Exp, class Val, class Tag>
1145 void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
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;
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));
1154 template <class Exp, class Val, class Tag>
1155 void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
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;
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));
1164 template <class Exp>
1165 void do_assign_function(const Exp& e, const mpl::int_<1>&)
1167 e.left().value()(&m_backend);
1169 template <class Exp>
1170 void do_assign_function(const Exp& e, const mpl::int_<2>&)
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());
1176 template <class F, class Exp>
1177 void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
1179 f(m_backend, function_arg_value(val));
1181 template <class F, class Exp, class Tag>
1182 void do_assign_function_1(const F& f, const Exp& val, const Tag&)
1185 f(m_backend, t.backend());
1187 template <class Exp>
1188 void do_assign_function(const Exp& e, const mpl::int_<3>&)
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());
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&)
1199 f(m_backend, function_arg_value(val1), function_arg_value(val2));
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&)
1204 self_type temp1(val1);
1205 f(m_backend, BOOST_MP_MOVE(temp1.backend()), function_arg_value(val2));
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&)
1210 self_type temp2(val2);
1211 f(m_backend, function_arg_value(val1), BOOST_MP_MOVE(temp2.backend()));
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&)
1216 self_type temp1(val1);
1217 self_type temp2(val2);
1218 f(m_backend, BOOST_MP_MOVE(temp1.backend()), BOOST_MP_MOVE(temp2.backend()));
1221 template <class Exp>
1222 void do_assign_function(const Exp& e, const mpl::int_<4>&)
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());
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)
1235 do_assign_function_3b(f, val1, val2, val3, t2, t3);
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)
1241 do_assign_function_3b(f, BOOST_MP_MOVE(t), val2, val3, t2, t3);
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)
1246 do_assign_function_3c(f, val1, val2, val3, t3);
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)
1252 do_assign_function_3c(f, val1, BOOST_MP_MOVE(t), val3, t3);
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&)
1257 f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));
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*/)
1263 do_assign_function_3c(f, val1, val2, BOOST_MP_MOVE(t), detail::terminal());
1266 template <class Exp>
1267 void do_add(const Exp& e, const detail::terminal&)
1269 using default_ops::eval_add;
1270 eval_add(m_backend, canonical_value(e.value()));
1273 template <class Exp>
1274 void do_add(const Exp& e, const detail::negate&)
1276 typedef typename Exp::left_type left_type;
1277 do_subtract(e.left(), typename left_type::tag_type());
1280 template <class Exp>
1281 void do_add(const Exp& e, const detail::plus&)
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());
1289 template <class Exp>
1290 void do_add(const Exp& e, const detail::minus&)
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());
1298 template <class Exp, class unknown>
1299 void do_add(const Exp& e, const unknown&)
1302 do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1305 template <class Exp>
1306 void do_add(const Exp& e, const detail::add_immediates&)
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()));
1312 template <class Exp>
1313 void do_add(const Exp& e, const detail::subtract_immediates&)
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()));
1320 template <class Exp>
1321 void do_subtract(const Exp& e, const detail::terminal&)
1323 using default_ops::eval_subtract;
1324 eval_subtract(m_backend, canonical_value(e.value()));
1327 template <class Exp>
1328 void do_subtract(const Exp& e, const detail::negate&)
1330 typedef typename Exp::left_type left_type;
1331 do_add(e.left(), typename left_type::tag_type());
1334 template <class Exp>
1335 void do_subtract(const Exp& e, const detail::plus&)
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());
1343 template <class Exp>
1344 void do_subtract(const Exp& e, const detail::minus&)
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());
1351 template <class Exp>
1352 void do_subtract(const Exp& e, const detail::add_immediates&)
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()));
1358 template <class Exp>
1359 void do_subtract(const Exp& e, const detail::subtract_immediates&)
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()));
1366 template <class Exp, class unknown>
1367 void do_subtract(const Exp& e, const unknown&)
1370 do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1373 template <class Exp>
1374 void do_multiplies(const Exp& e, const detail::terminal&)
1376 using default_ops::eval_multiply;
1377 eval_multiply(m_backend, canonical_value(e.value()));
1380 template <class Exp>
1381 void do_multiplies(const Exp& e, const detail::negate&)
1383 typedef typename Exp::left_type left_type;
1384 do_multiplies(e.left(), typename left_type::tag_type());
1388 template <class Exp>
1389 void do_multiplies(const Exp& e, const detail::multiplies&)
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());
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).
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&)
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());
1410 template <class Exp>
1411 void do_multiplies(const Exp& e, const detail::multiply_immediates&)
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()));
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).
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&)
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()));
1430 template <class Exp, class unknown>
1431 void do_multiplies(const Exp& e, const unknown&)
1433 using default_ops::eval_multiply;
1435 eval_multiply(m_backend, temp.m_backend);
1438 template <class Exp>
1439 void do_divide(const Exp& e, const detail::terminal&)
1441 using default_ops::eval_divide;
1442 eval_divide(m_backend, canonical_value(e.value()));
1445 template <class Exp>
1446 void do_divide(const Exp& e, const detail::negate&)
1448 typedef typename Exp::left_type left_type;
1449 do_divide(e.left(), typename left_type::tag_type());
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).
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&)
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());
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).
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&)
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());
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).
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&)
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()));
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).
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&)
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()));
1504 template <class Exp, class unknown>
1505 void do_divide(const Exp& e, const unknown&)
1507 using default_ops::eval_multiply;
1509 eval_divide(m_backend, temp.m_backend);
1512 template <class Exp>
1513 void do_modulus(const Exp& e, const detail::terminal&)
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()));
1520 template <class Exp, class Unknown>
1521 void do_modulus(const Exp& e, const Unknown&)
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;
1526 eval_modulus(m_backend, canonical_value(temp));
1529 template <class Exp>
1530 void do_bitwise_and(const Exp& e, const detail::terminal&)
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()));
1536 template <class Exp>
1537 void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
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());
1545 template <class Exp, class unknown>
1546 void do_bitwise_and(const Exp& e, const unknown&)
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;
1551 eval_bitwise_and(m_backend, temp.m_backend);
1554 template <class Exp>
1555 void do_bitwise_or(const Exp& e, const detail::terminal&)
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()));
1561 template <class Exp>
1562 void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
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());
1570 template <class Exp, class unknown>
1571 void do_bitwise_or(const Exp& e, const unknown&)
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;
1576 eval_bitwise_or(m_backend, temp.m_backend);
1579 template <class Exp>
1580 void do_bitwise_xor(const Exp& e, const detail::terminal&)
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()));
1586 template <class Exp>
1587 void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
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());
1595 template <class Exp, class unknown>
1596 void do_bitwise_xor(const Exp& e, const unknown&)
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;
1601 eval_bitwise_xor(m_backend, temp.m_backend);
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
1608 return contains_self(e, typename Exp::arity());
1610 template <class Exp>
1611 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
1613 return is_realy_self(e.value());
1615 template <class Exp>
1616 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<1> const&)const BOOST_NOEXCEPT
1618 typedef typename Exp::left_type child_type;
1619 return contains_self(e.left(), typename child_type::arity());
1621 template <class Exp>
1622 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<2> const&)const BOOST_NOEXCEPT
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());
1629 template <class Exp>
1630 BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<3> const&)const BOOST_NOEXCEPT
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());
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
1644 return is_self(e, typename Exp::arity());
1646 template <class Exp>
1647 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
1649 return is_realy_self(e.value());
1651 template <class Exp, int v>
1652 BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp&, mpl::int_<v> const&)const BOOST_NOEXCEPT
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; }
1661 static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); }
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(); }
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:
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(); }
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); }
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(); }
1688 template <class Backend, expression_template_option ExpressionTemplates>
1689 inline std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r)
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()))
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);
1700 s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);
1707 template <class tag, class A1, class A2, class A3, class A4>
1708 inline std::ostream& operator << (std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
1710 typedef typename expression<tag, A1, A2, A3, A4>::result_type value_type;
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.
1723 inline std::string read_string_while(std::istream& is, std::string const& permitted_chars)
1725 std::ios_base::iostate state = std::ios_base::goodbit;
1726 const std::istream::sentry sentry_check(is);
1731 int c = is.rdbuf()->sgetc();
1733 for(;; c = is.rdbuf()->snextc())
1734 if(std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
1736 state |= std::ios_base::eofbit;
1739 else if(permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
1741 // Invalid numeric character, stop reading:
1742 //is.rdbuf()->sputbackc(static_cast<char>(c));
1747 result.append(1, std::istream::traits_type::to_char_type(c));
1752 state |= std::ios_base::failbit;
1757 } // namespace detail
1759 template <class Backend, expression_template_option ExpressionTemplates>
1760 inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r)
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;
1765 switch(boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
1767 case boost::multiprecision::number_kind_integer:
1769 s = detail::read_string_while(is, "+-01234567");
1771 s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");
1773 s = detail::read_string_while(is, "+-0123456789");
1775 case boost::multiprecision::number_kind_floating_point:
1776 s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
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");
1790 is.setstate(std::istream::failbit);
1794 template <class Backend, expression_template_option ExpressionTemplates>
1795 BOOST_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>&>()))
1801 // Boost.Hash support, just call hash_value for the backend, which may or may not be supported:
1803 template <class Backend, expression_template_option ExpressionTemplates>
1804 inline std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
1806 return hash_value(val.backend());
1809 } // namespace multiprecision
1814 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1815 inline std::istream& operator >> (std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
1818 multiprecision::number<Backend, ExpressionTemplates> v1, v2;
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;
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'))))
1826 if(c == 'x' || c == 'X')
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");
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'))))
1842 if(c == 'x' || c == 'X')
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");
1859 template <class T, multiprecision::expression_template_option ExpressionTemplates>
1860 inline multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1862 return a.numerator();
1865 template <class T, multiprecision::expression_template_option ExpressionTemplates>
1866 inline multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1868 return a.denominator();
1871 namespace multiprecision
1875 struct component_type<boost::rational<I> >
1883 #pragma warning(pop)
1888 #ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
1890 #include <functional>
1894 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
1895 struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
1897 std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val)const { return hash_value(val); }
1904 #include <boost/multiprecision/detail/ublas_interop.hpp>