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_BIG_NUM_BASE_HPP
7 #define BOOST_MATH_BIG_NUM_BASE_HPP
10 #include <boost/utility/enable_if.hpp>
11 #include <boost/core/nvp.hpp>
12 #include <boost/type_traits/is_convertible.hpp>
13 #include <boost/type_traits/is_constructible.hpp>
14 #include <boost/type_traits/decay.hpp>
15 #include <boost/math/tools/complex.hpp>
18 #pragma warning(disable : 4307)
20 #include <boost/lexical_cast.hpp>
25 #if defined(NDEBUG) && !defined(_DEBUG)
26 #define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE
28 #define BOOST_MP_FORCEINLINE inline
31 #if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) || (defined(__clang_major__) && (__clang_major__ == 3) && (__clang_minor__ < 5))
32 #define BOOST_MP_NOEXCEPT_IF(x)
34 #define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
37 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
38 #define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
42 // Thread local storage:
43 // Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
45 #if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__)
46 #define BOOST_MP_THREAD_LOCAL thread_local
47 #define BOOST_MP_USING_THREAD_LOCAL
49 #define BOOST_MP_THREAD_LOCAL
53 # if __has_include(<version>)
55 # ifdef __cpp_lib_is_constant_evaluated
56 # include <type_traits>
57 # define BOOST_MP_HAS_IS_CONSTANT_EVALUATED
63 #if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
64 #define BOOST_MP_CLANG_CD
68 #if defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
69 # define BOOST_MP_IS_CONST_EVALUATED(x) std::is_constant_evaluated()
70 #elif (defined(BOOST_GCC) && !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9)) || defined(BOOST_MP_CLANG_CD)
71 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_is_constant_evaluated()
72 #elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_GCC) && (__GNUC__ >= 6)
73 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_constant_p(x)
75 # define BOOST_MP_NO_CONSTEXPR_DETECTION
78 #define BOOST_MP_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
80 // Early compiler versions trip over the constexpr code:
82 #if defined(__clang__) && (__clang_major__ < 5)
83 #undef BOOST_MP_CXX14_CONSTEXPR
84 #define BOOST_MP_CXX14_CONSTEXPR
86 #if defined(__apple_build_version__) && (__clang_major__ < 9)
87 #undef BOOST_MP_CXX14_CONSTEXPR
88 #define BOOST_MP_CXX14_CONSTEXPR
90 #if defined(BOOST_GCC) && (__GNUC__ < 6)
91 #undef BOOST_MP_CXX14_CONSTEXPR
92 #define BOOST_MP_CXX14_CONSTEXPR
95 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
96 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION
98 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION constexpr
102 #pragma warning(push)
103 #pragma warning(disable : 6326)
107 namespace multiprecision {
109 enum expression_template_option
115 template <class Backend>
116 struct expression_template_default
118 static const expression_template_option value = et_on;
121 template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
125 struct is_number : public mpl::false_
128 template <class Backend, expression_template_option ExpressionTemplates>
129 struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_
133 struct is_et_number : public mpl::false_
136 template <class Backend>
137 struct is_et_number<number<Backend, et_on> > : public mpl::true_
141 struct is_no_et_number : public mpl::false_
144 template <class Backend>
145 struct is_no_et_number<number<Backend, et_off> > : public mpl::true_
150 // Forward-declare an expression wrapper
151 template <class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
154 } // namespace detail
157 struct is_number_expression : public mpl::false_
160 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
161 struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_
164 template <class T, class Num>
165 struct is_compatible_arithmetic_type
167 is_convertible<T, Num>::value && !is_same<T, Num>::value && !is_number_expression<T>::value>
172 // Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
175 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
177 // This strange expression avoids a hardware trap in the corner case
178 // that val is the most negative value permitted in boost::long_long_type.
179 // See https://svn.boost.org/trac/boost/ticket/9740.
180 return t < 0 ? T(1u) + T(-(t + 1)) : t;
183 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
188 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
191 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), typename make_unsigned<T>::type>::type unsigned_abs(T t) BOOST_NOEXCEPT
193 // This strange expression avoids a hardware trap in the corner case
194 // that val is the most negative value permitted in boost::long_long_type.
195 // See https://svn.boost.org/trac/boost/ticket/9740.
196 return t < 0 ? static_cast<typename make_unsigned<T>::type>(1u) + static_cast<typename make_unsigned<T>::type>(-(t + 1)) : static_cast<typename make_unsigned<T>::type>(t);
199 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
207 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
208 #define BOOST_MP_MOVE(x) std::move(x)
210 #define BOOST_MP_MOVE(x) x
216 BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
217 static const unsigned value =
218 std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
219 : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
222 #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
224 struct bits_of<__float128>
226 static const unsigned value = 113;
231 struct has_enough_bits
234 struct type : public mpl::bool_<bits_of<T>::value >= b>
238 template <class Val, class Backend, class Tag>
241 typedef typename remove_cv<typename decay<const Val>::type>::type type;
243 template <class B, class Backend, class Tag>
244 struct canonical_imp<number<B, et_on>, Backend, Tag>
248 template <class B, class Backend, class Tag>
249 struct canonical_imp<number<B, et_off>, Backend, Tag>
254 template <class B, class Backend>
255 struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
259 template <class B, class Backend>
260 struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
265 template <class Val, class Backend>
266 struct canonical_imp<Val, Backend, mpl::int_<0> >
268 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
269 typedef typename mpl::find_if<
270 typename Backend::signed_types,
271 pred_type>::type iter_type;
272 typedef typename mpl::end<typename Backend::signed_types>::type end_type;
273 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
275 template <class Val, class Backend>
276 struct canonical_imp<Val, Backend, mpl::int_<1> >
278 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
279 typedef typename mpl::find_if<
280 typename Backend::unsigned_types,
281 pred_type>::type iter_type;
282 typedef typename mpl::end<typename Backend::unsigned_types>::type end_type;
283 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
285 template <class Val, class Backend>
286 struct canonical_imp<Val, Backend, mpl::int_<2> >
288 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
289 typedef typename mpl::find_if<
290 typename Backend::float_types,
291 pred_type>::type iter_type;
292 typedef typename mpl::end<typename Backend::float_types>::type end_type;
293 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
295 template <class Val, class Backend>
296 struct canonical_imp<Val, Backend, mpl::int_<3> >
298 typedef const char* type;
301 template <class Val, class Backend>
304 typedef typename mpl::if_<
311 is_floating_point<Val>,
315 is_convertible<Val, const char*>,
316 is_same<Val, std::string> >,
318 mpl::int_<4> >::type>::type>::type>::type tag_type;
320 typedef typename canonical_imp<Val, Backend, tag_type>::type type;
347 struct bitwise_complement
349 struct add_immediates
351 struct subtract_immediates
353 struct multiply_immediates
355 struct divide_immediates
357 struct modulus_immediates
359 struct bitwise_and_immediates
361 struct bitwise_or_immediates
363 struct bitwise_xor_immediates
365 struct complement_immediates
371 struct multiply_subtract
377 template <class T, expression_template_option ExpressionTemplates>
378 struct backend_type<number<T, ExpressionTemplates> >
383 template <class tag, class A1, class A2, class A3, class A4>
384 struct backend_type<expression<tag, A1, A2, A3, A4> >
386 typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
389 template <class T1, class T2>
390 struct combine_expression
392 #ifdef BOOST_NO_CXX11_DECLTYPE
393 typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
395 typedef decltype(T1() + T2()) type;
399 template <class T1, expression_template_option ExpressionTemplates, class T2>
400 struct combine_expression<number<T1, ExpressionTemplates>, T2>
402 typedef number<T1, ExpressionTemplates> type;
405 template <class T1, class T2, expression_template_option ExpressionTemplates>
406 struct combine_expression<T1, number<T2, ExpressionTemplates> >
408 typedef number<T2, ExpressionTemplates> type;
411 template <class T, expression_template_option ExpressionTemplates>
412 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
414 typedef number<T, ExpressionTemplates> type;
417 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
418 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
420 typedef typename mpl::if_c<
421 is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
422 number<T1, ExpressionTemplates1>,
423 number<T2, ExpressionTemplates2> >::type type;
429 typedef expression<terminal, T> type;
432 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
433 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
435 typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
440 unmentionable* proc() { return 0; }
443 typedef unmentionable* (unmentionable::*unmentionable_type)();
445 template <class T, bool b>
446 struct expression_storage_base
448 typedef const T& type;
452 struct expression_storage_base<T, true>
458 struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value>
462 struct expression_storage<T*>
468 struct expression_storage<const T*>
470 typedef const T* type;
473 template <class tag, class A1, class A2, class A3, class A4>
474 struct expression_storage<expression<tag, A1, A2, A3, A4> >
476 typedef expression<tag, A1, A2, A3, A4> type;
479 template <class tag, class Arg1>
480 struct expression<tag, Arg1, void, void, void>
482 typedef mpl::int_<1> arity;
483 typedef typename arg_type<Arg1>::type left_type;
484 typedef typename left_type::result_type left_result_type;
485 typedef typename left_type::result_type result_type;
486 typedef tag tag_type;
488 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
489 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
491 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
493 // If we have static_assert we can give a more useful error message
494 // than if we simply have no operator defined at all:
496 template <class Other>
497 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
499 // This should always fail:
500 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
503 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
505 // This should always fail:
506 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
509 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
511 // This should always fail:
512 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
515 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
517 // This should always fail:
518 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
521 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
523 // This should always fail:
524 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
527 template <class Other>
528 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
530 // This should always fail:
531 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
534 template <class Other>
535 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
537 // This should always fail:
538 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
541 template <class Other>
542 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
544 // This should always fail:
545 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
548 template <class Other>
549 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
551 // This should always fail:
552 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
555 template <class Other>
556 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
558 // This should always fail:
559 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
562 template <class Other>
563 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
565 // This should always fail:
566 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
569 template <class Other>
570 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
572 // This should always fail:
573 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
576 template <class Other>
577 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
579 // This should always fail:
580 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
583 template <class Other>
584 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
586 // This should always fail:
587 static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
590 template <class Other>
591 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
593 // This should always fail:
594 static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
599 BOOST_MP_CXX14_CONSTEXPR left_type left() const
601 return left_type(arg);
604 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg; }
606 static const unsigned depth = left_type::depth + 1;
607 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
608 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
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:
614 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
615 explicit operator T() const
617 result_type r(*this);
618 return static_cast<bool>(r);
620 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
621 explicit operator T() const
623 return static_cast<T>(static_cast<result_type>(*this));
629 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
632 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
634 return static_cast<T>(static_cast<result_type>(*this));
636 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
638 result_type r(*this);
639 return static_cast<bool>(r);
641 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
642 BOOST_MP_FORCEINLINE explicit operator void() const
647 operator unmentionable_type() const
649 result_type r(*this);
650 return r ? &unmentionable::proc : 0;
655 BOOST_MP_CXX14_CONSTEXPR T convert_to()
657 result_type r(*this);
658 return r.template convert_to<T>();
662 typename expression_storage<Arg1>::type arg;
663 expression& operator=(const expression&);
666 template <class Arg1>
667 struct expression<terminal, Arg1, void, void, void>
669 typedef mpl::int_<0> arity;
670 typedef Arg1 result_type;
671 typedef terminal tag_type;
673 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
674 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
676 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
678 // If we have static_assert we can give a more useful error message
679 // than if we simply have no operator defined at all:
681 template <class Other>
682 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
684 // This should always fail:
685 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
688 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
690 // This should always fail:
691 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
694 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
696 // This should always fail:
697 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
700 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
702 // This should always fail:
703 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
706 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
708 // This should always fail:
709 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
712 template <class Other>
713 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
715 // This should always fail:
716 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
719 template <class Other>
720 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
722 // This should always fail:
723 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
726 template <class Other>
727 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
729 // This should always fail:
730 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
733 template <class Other>
734 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
736 // This should always fail:
737 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
740 template <class Other>
741 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
743 // This should always fail:
744 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
747 template <class Other>
748 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
750 // This should always fail:
751 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
754 template <class Other>
755 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
757 // This should always fail:
758 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
761 template <class Other>
762 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
764 // This should always fail:
765 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
768 template <class Other>
769 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
771 // This should always fail:
772 static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
775 template <class Other>
776 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
778 // This should always fail:
779 static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
784 BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const BOOST_NOEXCEPT
789 static const unsigned depth = 0;
791 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
792 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
794 // Horrible workaround for gcc-4.6.x which always prefers the template
795 // operator bool() rather than the non-template operator when converting to
796 // an arithmetic type:
798 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
799 explicit operator T() const
801 result_type r(*this);
802 return static_cast<bool>(r);
804 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
805 explicit operator T() const
807 return static_cast<T>(static_cast<result_type>(*this));
813 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
816 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
818 return static_cast<T>(static_cast<result_type>(*this));
820 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
822 result_type r(*this);
823 return static_cast<bool>(r);
825 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
826 BOOST_MP_FORCEINLINE explicit operator void() const
831 operator unmentionable_type() const
833 return arg ? &unmentionable::proc : 0;
838 BOOST_MP_CXX14_CONSTEXPR T convert_to()
840 result_type r(*this);
841 return r.template convert_to<T>();
845 typename expression_storage<Arg1>::type arg;
846 expression& operator=(const expression&);
849 template <class tag, class Arg1, class Arg2>
850 struct expression<tag, Arg1, Arg2, void, void>
852 typedef mpl::int_<2> arity;
853 typedef typename arg_type<Arg1>::type left_type;
854 typedef typename arg_type<Arg2>::type right_type;
855 typedef typename left_type::result_type left_result_type;
856 typedef typename right_type::result_type right_result_type;
857 typedef typename combine_expression<left_result_type, right_result_type>::type result_type;
858 typedef tag tag_type;
860 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
861 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
863 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
865 // If we have static_assert we can give a more useful error message
866 // than if we simply have no operator defined at all:
868 template <class Other>
869 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
871 // This should always fail:
872 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
875 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
877 // This should always fail:
878 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
881 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
883 // This should always fail:
884 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
887 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
889 // This should always fail:
890 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
893 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
895 // This should always fail:
896 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
899 template <class Other>
900 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
902 // This should always fail:
903 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
906 template <class Other>
907 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
909 // This should always fail:
910 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
913 template <class Other>
914 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
916 // This should always fail:
917 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
920 template <class Other>
921 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
923 // This should always fail:
924 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
927 template <class Other>
928 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
930 // This should always fail:
931 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
934 template <class Other>
935 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
937 // This should always fail:
938 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
941 template <class Other>
942 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
944 // This should always fail:
945 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
948 template <class Other>
949 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
951 // This should always fail:
952 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
955 template <class Other>
956 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
958 // This should always fail:
959 static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
962 template <class Other>
963 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
965 // This should always fail:
966 static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
971 BOOST_MP_CXX14_CONSTEXPR left_type left() const
973 return left_type(arg1);
975 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg2); }
976 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
977 BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const BOOST_NOEXCEPT { return arg2; }
979 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
980 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
982 // Horrible workaround for gcc-4.6.x which always prefers the template
983 // operator bool() rather than the non-template operator when converting to
984 // an arithmetic type:
986 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
987 explicit operator T() const
989 result_type r(*this);
990 return static_cast<bool>(r);
992 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
993 explicit operator T() const
995 return static_cast<T>(static_cast<result_type>(*this));
1001 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
1004 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1006 return static_cast<T>(static_cast<result_type>(*this));
1008 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1010 result_type r(*this);
1011 return static_cast<bool>(r);
1013 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
1014 BOOST_MP_FORCEINLINE explicit operator void() const
1019 operator unmentionable_type() const
1021 result_type r(*this);
1022 return r ? &unmentionable::proc : 0;
1026 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1028 result_type r(*this);
1029 return r.template convert_to<T>();
1032 static const BOOST_MP_CXX14_CONSTEXPR unsigned left_depth = left_type::depth + 1;
1033 static const BOOST_MP_CXX14_CONSTEXPR unsigned right_depth = right_type::depth + 1;
1034 static const BOOST_MP_CXX14_CONSTEXPR unsigned depth = left_depth > right_depth ? left_depth : right_depth;
1037 typename expression_storage<Arg1>::type arg1;
1038 typename expression_storage<Arg2>::type arg2;
1039 expression& operator=(const expression&);
1042 template <class tag, class Arg1, class Arg2, class Arg3>
1043 struct expression<tag, Arg1, Arg2, Arg3, void>
1045 typedef mpl::int_<3> arity;
1046 typedef typename arg_type<Arg1>::type left_type;
1047 typedef typename arg_type<Arg2>::type middle_type;
1048 typedef typename arg_type<Arg3>::type right_type;
1049 typedef typename left_type::result_type left_result_type;
1050 typedef typename middle_type::result_type middle_result_type;
1051 typedef typename right_type::result_type right_result_type;
1052 typedef typename combine_expression<
1054 typename combine_expression<right_result_type, middle_result_type>::type>::type result_type;
1055 typedef tag tag_type;
1057 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
1058 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
1060 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1062 // If we have static_assert we can give a more useful error message
1063 // than if we simply have no operator defined at all:
1065 template <class Other>
1066 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1068 // This should always fail:
1069 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1072 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1074 // This should always fail:
1075 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1078 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1080 // This should always fail:
1081 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1084 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1086 // This should always fail:
1087 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1090 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1092 // This should always fail:
1093 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1096 template <class Other>
1097 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1099 // This should always fail:
1100 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1103 template <class Other>
1104 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1106 // This should always fail:
1107 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1110 template <class Other>
1111 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1113 // This should always fail:
1114 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1117 template <class Other>
1118 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1120 // This should always fail:
1121 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1124 template <class Other>
1125 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1127 // This should always fail:
1128 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1131 template <class Other>
1132 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1134 // This should always fail:
1135 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1138 template <class Other>
1139 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1141 // This should always fail:
1142 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1145 template <class Other>
1146 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1148 // This should always fail:
1149 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1152 template <class Other>
1153 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1155 // This should always fail:
1156 static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1159 template <class Other>
1160 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1162 // This should always fail:
1163 static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1168 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1170 return left_type(arg1);
1172 BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
1173 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg3); }
1174 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
1175 BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const BOOST_NOEXCEPT { return arg2; }
1176 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const BOOST_NOEXCEPT { return arg3; }
1178 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1179 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1181 // Horrible workaround for gcc-4.6.x which always prefers the template
1182 // operator bool() rather than the non-template operator when converting to
1183 // an arithmetic type:
1185 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
1186 explicit operator T() const
1188 result_type r(*this);
1189 return static_cast<bool>(r);
1191 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
1192 explicit operator T() const
1194 return static_cast<T>(static_cast<result_type>(*this));
1200 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
1203 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1205 return static_cast<T>(static_cast<result_type>(*this));
1207 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1209 result_type r(*this);
1210 return static_cast<bool>(r);
1212 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
1213 BOOST_MP_FORCEINLINE explicit operator void() const
1218 operator unmentionable_type() const
1220 result_type r(*this);
1221 return r ? &unmentionable::proc : 0;
1225 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1227 result_type r(*this);
1228 return r.template convert_to<T>();
1231 static const unsigned left_depth = left_type::depth + 1;
1232 static const unsigned middle_depth = middle_type::depth + 1;
1233 static const unsigned right_depth = right_type::depth + 1;
1234 static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
1237 typename expression_storage<Arg1>::type arg1;
1238 typename expression_storage<Arg2>::type arg2;
1239 typename expression_storage<Arg3>::type arg3;
1240 expression& operator=(const expression&);
1243 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1246 typedef mpl::int_<4> arity;
1247 typedef typename arg_type<Arg1>::type left_type;
1248 typedef typename arg_type<Arg2>::type left_middle_type;
1249 typedef typename arg_type<Arg3>::type right_middle_type;
1250 typedef typename arg_type<Arg4>::type right_type;
1251 typedef typename left_type::result_type left_result_type;
1252 typedef typename left_middle_type::result_type left_middle_result_type;
1253 typedef typename right_middle_type::result_type right_middle_result_type;
1254 typedef typename right_type::result_type right_result_type;
1255 typedef typename combine_expression<
1257 typename combine_expression<
1258 left_middle_result_type,
1259 typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type result_type;
1260 typedef tag tag_type;
1262 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {}
1263 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
1265 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1267 // If we have static_assert we can give a more useful error message
1268 // than if we simply have no operator defined at all:
1270 template <class Other>
1271 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1273 // This should always fail:
1274 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1277 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1279 // This should always fail:
1280 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1283 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1285 // This should always fail:
1286 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1289 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1291 // This should always fail:
1292 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1295 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1297 // This should always fail:
1298 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1301 template <class Other>
1302 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1304 // This should always fail:
1305 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1308 template <class Other>
1309 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1311 // This should always fail:
1312 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1315 template <class Other>
1316 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1318 // This should always fail:
1319 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1322 template <class Other>
1323 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1325 // This should always fail:
1326 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1329 template <class Other>
1330 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1332 // This should always fail:
1333 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1336 template <class Other>
1337 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1339 // This should always fail:
1340 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1343 template <class Other>
1344 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1346 // This should always fail:
1347 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1350 template <class Other>
1351 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1353 // This should always fail:
1354 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1357 template <class Other>
1358 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1360 // This should always fail:
1361 static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1364 template <class Other>
1365 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1367 // This should always fail:
1368 static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1373 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1375 return left_type(arg1);
1377 BOOST_MP_CXX14_CONSTEXPR left_middle_type left_middle() const { return left_middle_type(arg2); }
1378 BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
1379 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg4); }
1380 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
1381 BOOST_MP_CXX14_CONSTEXPR const Arg2& left_middle_ref() const BOOST_NOEXCEPT { return arg2; }
1382 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_middle_ref() const BOOST_NOEXCEPT { return arg3; }
1383 BOOST_MP_CXX14_CONSTEXPR const Arg4& right_ref() const BOOST_NOEXCEPT { return arg4; }
1385 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1386 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1388 // Horrible workaround for gcc-4.6.x which always prefers the template
1389 // operator bool() rather than the non-template operator when converting to
1390 // an arithmetic type:
1392 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
1393 explicit operator T() const
1395 result_type r(*this);
1396 return static_cast<bool>(r);
1398 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
1399 explicit operator T() const
1401 return static_cast<T>(static_cast<result_type>(*this));
1407 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
1410 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1412 return static_cast<T>(static_cast<result_type>(*this));
1414 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1416 result_type r(*this);
1417 return static_cast<bool>(r);
1419 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
1420 BOOST_MP_FORCEINLINE explicit operator void() const
1425 operator unmentionable_type() const
1427 result_type r(*this);
1428 return r ? &unmentionable::proc : 0;
1432 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1434 result_type r(*this);
1435 return r.template convert_to<T>();
1438 static const unsigned left_depth = left_type::depth + 1;
1439 static const unsigned left_middle_depth = left_middle_type::depth + 1;
1440 static const unsigned right_middle_depth = right_middle_type::depth + 1;
1441 static const unsigned right_depth = right_type::depth + 1;
1443 static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
1444 static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
1446 static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
1449 typename expression_storage<Arg1>::type arg1;
1450 typename expression_storage<Arg2>::type arg2;
1451 typename expression_storage<Arg3>::type arg3;
1452 typename expression_storage<Arg4>::type arg4;
1453 expression& operator=(const expression&);
1459 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
1460 BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
1461 // If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
1462 BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
1463 static const long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
1464 static inline BOOST_CONSTEXPR long value() BOOST_NOEXCEPT { return m_value; }
1467 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
1469 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1471 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1476 void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
1478 typedef typename S::size_type size_type;
1479 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
1480 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
1481 bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
1482 bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
1484 bool neg = str.size() && (str[0] == '-');
1491 digits = (std::max)(str.size(), size_type(16));
1494 if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
1496 // We will be printing zero, even though the value might not
1497 // actually be zero (it just may have been rounded to zero).
1499 if (scientific || fixed)
1502 str.append(size_type(digits), '0');
1512 str.append(size_type(digits - 1), '0');
1516 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1518 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1522 if (!fixed && !scientific && !showpoint)
1525 // Suppress trailing zeros:
1527 std::string::iterator pos = str.end();
1528 while (pos != str.begin() && *--pos == '0')
1531 if (pos != str.end())
1533 str.erase(pos, str.end());
1537 else if (!fixed || (my_exp >= 0))
1540 // Pad out the end with zero's if we need to:
1542 boost::intmax_t chars = str.size();
1543 chars = digits - chars;
1548 str.append(static_cast<std::string::size_type>(chars), '0');
1552 if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
1554 if (1 + my_exp > static_cast<boost::intmax_t>(str.size()))
1556 // Just pad out the end with zeros:
1557 str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
1558 if (showpoint || fixed)
1561 else if (my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
1565 str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
1566 str.insert(static_cast<std::string::size_type>(0), "0.");
1570 // Insert the decimal point:
1571 str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
1574 else if (showpoint || fixed) // we have exactly the digits we require to left of the point
1579 // We may need to add trailing zeros:
1580 boost::intmax_t l = str.find('.') + 1;
1581 l = digits - (str.size() - l);
1583 str.append(size_type(l), '0');
1589 // Scientific format:
1590 if (showpoint || (str.size() > 1))
1591 str.insert(static_cast<std::string::size_type>(1u), 1, '.');
1592 str.append(static_cast<std::string::size_type>(1u), 'e');
1593 S e = boost::lexical_cast<S>(abs(my_exp));
1594 if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
1595 e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
1597 e.insert(static_cast<std::string::size_type>(0), 1, '-');
1599 e.insert(static_cast<std::string::size_type>(0), 1, '+');
1603 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1605 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1609 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
1611 if (val > (std::numeric_limits<std::size_t>::max)())
1612 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1614 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1617 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
1620 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1623 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
1625 if (val > (std::numeric_limits<std::size_t>::max)())
1626 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1629 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT {}
1632 BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
1633 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1634 BOOST_MP_CXX14_CONSTEXPR typename expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type evaluate_if_expression(const expression<tag, Arg1, Arg2, Arg3, Arg4>& val) { return val; }
1636 } // namespace detail
1639 // Traits class, lets us know what kind of number we have, defaults to a floating point type:
1641 enum number_category_type
1643 number_kind_unknown = -1,
1644 number_kind_integer = 0,
1645 number_kind_floating_point = 1,
1646 number_kind_rational = 2,
1647 number_kind_fixed_point = 3,
1648 number_kind_complex = 4
1651 template <class Num, bool, bool>
1652 struct number_category_base : public mpl::int_<number_kind_unknown>
1654 template <class Num>
1655 struct number_category_base<Num, true, false> : public mpl::int_<std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)>
1657 template <class Num>
1658 struct number_category : public number_category_base<Num, boost::is_class<Num>::value || boost::is_arithmetic<Num>::value, boost::is_abstract<Num>::value>
1660 template <class Backend, expression_template_option ExpressionTemplates>
1661 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
1663 template <class tag, class A1, class A2, class A3, class A4>
1664 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1667 // Specializations for types which do not always have numberic_limits specializations:
1669 #ifdef BOOST_HAS_INT128
1671 struct number_category<boost::int128_type> : public mpl::int_<number_kind_integer>
1674 struct number_category<boost::uint128_type> : public mpl::int_<number_kind_integer>
1677 #ifdef BOOST_HAS_FLOAT128
1679 struct number_category<__float128> : public mpl::int_<number_kind_floating_point>
1684 struct component_type
1688 template <class tag, class A1, class A2, class A3, class A4>
1689 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1693 struct scalar_result_from_possible_complex
1695 typedef typename mpl::if_c<number_category<T>::value == number_kind_complex,
1696 typename component_type<T>::type, T>::type type;
1700 struct complex_result_from_scalar; // individual backends must specialize this trait.
1703 struct is_unsigned_number : public mpl::false_
1705 template <class Backend, expression_template_option ExpressionTemplates>
1706 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
1709 struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value>
1712 struct is_interval_number : public mpl::false_
1714 template <class Backend, expression_template_option ExpressionTemplates>
1715 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
1718 } // namespace multiprecision
1719 } // namespace boost
1721 namespace boost { namespace math {
1727 template <class tag, class A1, class A2, class A3, class A4>
1728 struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
1730 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
1733 template <class R, class B, boost::multiprecision::expression_template_option ET>
1734 inline R real_cast(const boost::multiprecision::number<B, ET>& val)
1736 return val.template convert_to<R>();
1739 template <class R, class tag, class A1, class A2, class A3, class A4>
1740 inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
1742 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
1743 return val_type(val).template convert_to<R>();
1746 template <class B, boost::multiprecision::expression_template_option ET>
1747 struct is_complex_type<boost::multiprecision::number<B, ET> > : public boost::mpl::bool_<boost::multiprecision::number_category<B>::value == boost::multiprecision::number_kind_complex> {};
1749 } // namespace tools
1751 namespace constants {
1754 struct is_explicitly_convertible_from_string;
1756 template <class B, boost::multiprecision::expression_template_option ET>
1757 struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
1759 static const bool value = true;
1762 } // namespace constants
1764 }} // namespace boost::math
1767 #pragma warning(pop)
1770 #endif // BOOST_MATH_BIG_NUM_BASE_HPP