• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ///////////////////////////////////////////////////////////////////////////////
2 //  Copyright 2011 John Maddock. Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef BOOST_MATH_BIG_NUM_BASE_HPP
7 #define BOOST_MATH_BIG_NUM_BASE_HPP
8 
9 #include <limits>
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>
16 #ifdef BOOST_MSVC
17 #pragma warning(push)
18 #pragma warning(disable : 4307)
19 #endif
20 #include <boost/lexical_cast.hpp>
21 #ifdef BOOST_MSVC
22 #pragma warning(pop)
23 #endif
24 
25 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_NO_CXX11_HDR_ARRAY)\
26       || defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) || defined(BOOST_NO_CXX11_CONSTEXPR)\
27       || defined(BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || defined(BOOST_NO_CXX11_REF_QUALIFIERS) || defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)\
28       || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_USER_DEFINED_LITERALS) || defined(BOOST_NO_CXX11_THREAD_LOCAL)\
29       || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_STATIC_ASSERT) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)\
30       || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_REF_QUALIFIERS)
31 //
32 // The above list includes everything we use, plus a few we're likely to use soon.
33 // As from March 2020, C++03 support is deprecated, and as from March 2021 will be removed,
34 // so mark up as such:
35 //
36 #if (defined(_MSC_VER) || defined(__GNUC__)) && !defined(BOOST_MP_DISABLE_DEPRECATE_03_WARNING)
37 #pragma message("CAUTION: One or more C++11 features were found to be unavailable")
38 #pragma message("CAUTION: Compiling Boost.Multiprecision in non-C++11 or later conformance modes is now deprecated and will be removed from March 2021.")
39 #pragma message("CAUTION: Define BOOST_MP_DISABLE_DEPRECATE_03_WARNING to suppress this message.")
40 #endif
41 #endif
42 
43 #if defined(NDEBUG) && !defined(_DEBUG)
44 #define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE
45 #else
46 #define BOOST_MP_FORCEINLINE inline
47 #endif
48 
49 #if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) || (defined(__clang_major__) && (__clang_major__ == 3) && (__clang_minor__ < 5))
50 #define BOOST_MP_NOEXCEPT_IF(x)
51 #else
52 #define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
53 #endif
54 
55 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
56 #define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
57 #endif
58 
59 //
60 // Thread local storage:
61 // Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
62 //
63 #if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__)
64 #define BOOST_MP_THREAD_LOCAL thread_local
65 #define BOOST_MP_USING_THREAD_LOCAL
66 #else
67 #define BOOST_MP_THREAD_LOCAL
68 #endif
69 
70 #ifdef __has_include
71 # if __has_include(<version>)
72 #  include <version>
73 #  ifdef __cpp_lib_is_constant_evaluated
74 #   include <type_traits>
75 #   define BOOST_MP_HAS_IS_CONSTANT_EVALUATED
76 #  endif
77 # endif
78 #endif
79 
80 #ifdef __has_builtin
81 #if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
82 #define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
83 #endif
84 #endif
85 //
86 // MSVC also supports __builtin_is_constant_evaluated if it's recent enough:
87 //
88 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 192528326)
89 #  define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
90 #endif
91 //
92 // As does GCC-9:
93 //
94 #if defined(BOOST_GCC) && !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9) && !defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
95 #  define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
96 #endif
97 
98 #if defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
99 #  define BOOST_MP_IS_CONST_EVALUATED(x) std::is_constant_evaluated()
100 #elif defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
101 #  define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_is_constant_evaluated()
102 #elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_GCC) && (__GNUC__ >= 6)
103 #  define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_constant_p(x)
104 #else
105 #  define BOOST_MP_NO_CONSTEXPR_DETECTION
106 #endif
107 
108 #define BOOST_MP_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
109 //
110 // Early compiler versions trip over the constexpr code:
111 //
112 #if defined(__clang__) && (__clang_major__ < 5)
113 #undef BOOST_MP_CXX14_CONSTEXPR
114 #define BOOST_MP_CXX14_CONSTEXPR
115 #endif
116 #if defined(__apple_build_version__) && (__clang_major__ < 9)
117 #undef BOOST_MP_CXX14_CONSTEXPR
118 #define BOOST_MP_CXX14_CONSTEXPR
119 #endif
120 #if defined(BOOST_GCC) && (__GNUC__ < 6)
121 #undef BOOST_MP_CXX14_CONSTEXPR
122 #define BOOST_MP_CXX14_CONSTEXPR
123 #endif
124 #if defined(BOOST_INTEL)
125 #undef BOOST_MP_CXX14_CONSTEXPR
126 #define BOOST_MP_CXX14_CONSTEXPR
127 #define BOOST_MP_NO_CONSTEXPR_DETECTION
128 #endif
129 
130 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
131 #  define BOOST_CXX14_CONSTEXPR_IF_DETECTION
132 #else
133 #  define BOOST_CXX14_CONSTEXPR_IF_DETECTION constexpr
134 #endif
135 
136 #ifdef BOOST_MSVC
137 #pragma warning(push)
138 #pragma warning(disable : 6326)
139 #endif
140 
141 namespace boost {
142 namespace multiprecision {
143 
144 enum expression_template_option
145 {
146    et_off = 0,
147    et_on  = 1
148 };
149 
150 template <class Backend>
151 struct expression_template_default
152 {
153    static const expression_template_option value = et_on;
154 };
155 
156 template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
157 class number;
158 
159 template <class T>
160 struct is_number : public mpl::false_
161 {};
162 
163 template <class Backend, expression_template_option ExpressionTemplates>
164 struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_
165 {};
166 
167 template <class T>
168 struct is_et_number : public mpl::false_
169 {};
170 
171 template <class Backend>
172 struct is_et_number<number<Backend, et_on> > : public mpl::true_
173 {};
174 
175 template <class T>
176 struct is_no_et_number : public mpl::false_
177 {};
178 
179 template <class Backend>
180 struct is_no_et_number<number<Backend, et_off> > : public mpl::true_
181 {};
182 
183 namespace detail {
184 
185 // Forward-declare an expression wrapper
186 template <class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
187 struct expression;
188 
189 } // namespace detail
190 
191 template <class T>
192 struct is_number_expression : public mpl::false_
193 {};
194 
195 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
196 struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_
197 {};
198 
199 template <class T, class Num>
200 struct is_compatible_arithmetic_type
201     : public mpl::bool_<
202           is_convertible<T, Num>::value && !is_same<T, Num>::value && !is_number_expression<T>::value>
203 {};
204 
205 namespace detail {
206 //
207 // Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
208 //
209 template <class T>
abs(T t)210 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
211 {
212    // This strange expression avoids a hardware trap in the corner case
213    // that val is the most negative value permitted in boost::long_long_type.
214    // See https://svn.boost.org/trac/boost/ticket/9740.
215    return t < 0 ? T(1u) + T(-(t + 1)) : t;
216 }
217 template <class T>
abs(T t)218 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
219 {
220    return t;
221 }
222 
223 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
224 
225 template <class T>
unsigned_abs(T t)226 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
227 {
228    // This strange expression avoids a hardware trap in the corner case
229    // that val is the most negative value permitted in boost::long_long_type.
230    // See https://svn.boost.org/trac/boost/ticket/9740.
231    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);
232 }
233 template <class T>
unsigned_abs(T t)234 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
235 {
236    return t;
237 }
238 
239 //
240 // Move support:
241 //
242 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
243 #define BOOST_MP_MOVE(x) std::move(x)
244 #else
245 #define BOOST_MP_MOVE(x) x
246 #endif
247 
248 template <class T>
249 struct bits_of
250 {
251    BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
252    static const unsigned value =
253        std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
254                                               : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
255 };
256 
257 #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
258 #define BOOST_MP_BITS_OF_FLOAT128_DEFINED
259 template <>
260 struct bits_of<__float128>
261 {
262    static const unsigned value = 113;
263 };
264 #endif
265 
266 template <int b>
267 struct has_enough_bits
268 {
269    template <class T>
270    struct type : public mpl::bool_<bits_of<T>::value >= b>
271    {};
272 };
273 
274 template <class Val, class Backend, class Tag>
275 struct canonical_imp
276 {
277    typedef typename remove_cv<typename decay<const Val>::type>::type type;
278 };
279 template <class B, class Backend, class Tag>
280 struct canonical_imp<number<B, et_on>, Backend, Tag>
281 {
282    typedef B type;
283 };
284 template <class B, class Backend, class Tag>
285 struct canonical_imp<number<B, et_off>, Backend, Tag>
286 {
287    typedef B type;
288 };
289 #ifdef __SUNPRO_CC
290 template <class B, class Backend>
291 struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
292 {
293    typedef B type;
294 };
295 template <class B, class Backend>
296 struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
297 {
298    typedef B type;
299 };
300 #endif
301 template <class Val, class Backend>
302 struct canonical_imp<Val, Backend, mpl::int_<0> >
303 {
304    typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
305    typedef typename mpl::find_if<
306        typename Backend::signed_types,
307        pred_type>::type                                                                                                 iter_type;
308    typedef typename mpl::end<typename Backend::signed_types>::type                                                      end_type;
309    typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
310 };
311 template <class Val, class Backend>
312 struct canonical_imp<Val, Backend, mpl::int_<1> >
313 {
314    typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
315    typedef typename mpl::find_if<
316        typename Backend::unsigned_types,
317        pred_type>::type                                                                                                 iter_type;
318    typedef typename mpl::end<typename Backend::unsigned_types>::type                                                    end_type;
319    typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
320 };
321 template <class Val, class Backend>
322 struct canonical_imp<Val, Backend, mpl::int_<2> >
323 {
324    typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
325    typedef typename mpl::find_if<
326        typename Backend::float_types,
327        pred_type>::type                                                                                                 iter_type;
328    typedef typename mpl::end<typename Backend::float_types>::type                                                       end_type;
329    typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
330 };
331 template <class Val, class Backend>
332 struct canonical_imp<Val, Backend, mpl::int_<3> >
333 {
334    typedef const char* type;
335 };
336 
337 template <class Val, class Backend>
338 struct canonical
339 {
340    typedef typename mpl::if_<
341        is_signed<Val>,
342        mpl::int_<0>,
343        typename mpl::if_<
344            is_unsigned<Val>,
345            mpl::int_<1>,
346            typename mpl::if_<
347                is_floating_point<Val>,
348                mpl::int_<2>,
349                typename mpl::if_<
350                    mpl::or_<
351                        is_convertible<Val, const char*>,
352                        is_same<Val, std::string> >,
353                    mpl::int_<3>,
354                    mpl::int_<4> >::type>::type>::type>::type tag_type;
355 
356    typedef typename canonical_imp<Val, Backend, tag_type>::type type;
357 };
358 
359 struct terminal
360 {};
361 struct negate
362 {};
363 struct plus
364 {};
365 struct minus
366 {};
367 struct multiplies
368 {};
369 struct divides
370 {};
371 struct modulus
372 {};
373 struct shift_left
374 {};
375 struct shift_right
376 {};
377 struct bitwise_and
378 {};
379 struct bitwise_or
380 {};
381 struct bitwise_xor
382 {};
383 struct bitwise_complement
384 {};
385 struct add_immediates
386 {};
387 struct subtract_immediates
388 {};
389 struct multiply_immediates
390 {};
391 struct divide_immediates
392 {};
393 struct modulus_immediates
394 {};
395 struct bitwise_and_immediates
396 {};
397 struct bitwise_or_immediates
398 {};
399 struct bitwise_xor_immediates
400 {};
401 struct complement_immediates
402 {};
403 struct function
404 {};
405 struct multiply_add
406 {};
407 struct multiply_subtract
408 {};
409 
410 template <class T>
411 struct backend_type;
412 
413 template <class T, expression_template_option ExpressionTemplates>
414 struct backend_type<number<T, ExpressionTemplates> >
415 {
416    typedef T type;
417 };
418 
419 template <class tag, class A1, class A2, class A3, class A4>
420 struct backend_type<expression<tag, A1, A2, A3, A4> >
421 {
422    typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
423 };
424 
425 template <class T1, class T2>
426 struct combine_expression
427 {
428 #ifdef BOOST_NO_CXX11_DECLTYPE
429    typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
430 #else
431    typedef decltype(T1() + T2()) type;
432 #endif
433 };
434 
435 template <class T1, expression_template_option ExpressionTemplates, class T2>
436 struct combine_expression<number<T1, ExpressionTemplates>, T2>
437 {
438    typedef number<T1, ExpressionTemplates> type;
439 };
440 
441 template <class T1, class T2, expression_template_option ExpressionTemplates>
442 struct combine_expression<T1, number<T2, ExpressionTemplates> >
443 {
444    typedef number<T2, ExpressionTemplates> type;
445 };
446 
447 template <class T, expression_template_option ExpressionTemplates>
448 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
449 {
450    typedef number<T, ExpressionTemplates> type;
451 };
452 
453 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
454 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
455 {
456    typedef typename mpl::if_c<
457        is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
458        number<T1, ExpressionTemplates1>,
459        number<T2, ExpressionTemplates2> >::type type;
460 };
461 
462 template <class T>
463 struct arg_type
464 {
465    typedef expression<terminal, T> type;
466 };
467 
468 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
469 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
470 {
471    typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
472 };
473 
474 struct unmentionable
475 {
procboost::multiprecision::detail::unmentionable476    unmentionable* proc() { return 0; }
477 };
478 
479 typedef unmentionable* (unmentionable::*unmentionable_type)();
480 
481 template <class T, bool b>
482 struct expression_storage_base
483 {
484    typedef const T& type;
485 };
486 
487 template <class T>
488 struct expression_storage_base<T, true>
489 {
490    typedef T type;
491 };
492 
493 template <class T>
494 struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value>
495 {};
496 
497 template <class T>
498 struct expression_storage<T*>
499 {
500    typedef T* type;
501 };
502 
503 template <class T>
504 struct expression_storage<const T*>
505 {
506    typedef const T* type;
507 };
508 
509 template <class tag, class A1, class A2, class A3, class A4>
510 struct expression_storage<expression<tag, A1, A2, A3, A4> >
511 {
512    typedef expression<tag, A1, A2, A3, A4> type;
513 };
514 
515 template <class tag, class Arg1>
516 struct expression<tag, Arg1, void, void, void>
517 {
518    typedef mpl::int_<1>                    arity;
519    typedef typename arg_type<Arg1>::type   left_type;
520    typedef typename left_type::result_type left_result_type;
521    typedef typename left_type::result_type result_type;
522    typedef tag                             tag_type;
523 
expressionboost::multiprecision::detail::expression524    explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
expressionboost::multiprecision::detail::expression525    BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
526 
527 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
528    //
529    // If we have static_assert we can give a more useful error message
530    // than if we simply have no operator defined at all:
531    //
532    template <class Other>
operator =boost::multiprecision::detail::expression533    BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
534    {
535       // This should always fail:
536       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?");
537       return *this;
538    }
operator ++boost::multiprecision::detail::expression539    BOOST_MP_CXX14_CONSTEXPR expression& operator++()
540    {
541       // This should always fail:
542       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?");
543       return *this;
544    }
operator ++boost::multiprecision::detail::expression545    BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
546    {
547       // This should always fail:
548       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?");
549       return *this;
550    }
operator --boost::multiprecision::detail::expression551    BOOST_MP_CXX14_CONSTEXPR expression& operator--()
552    {
553       // This should always fail:
554       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?");
555       return *this;
556    }
operator --boost::multiprecision::detail::expression557    BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
558    {
559       // This should always fail:
560       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?");
561       return *this;
562    }
563    template <class Other>
operator +=boost::multiprecision::detail::expression564    BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
565    {
566       // This should always fail:
567       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?");
568       return *this;
569    }
570    template <class Other>
operator -=boost::multiprecision::detail::expression571    BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
572    {
573       // This should always fail:
574       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?");
575       return *this;
576    }
577    template <class Other>
operator *=boost::multiprecision::detail::expression578    BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
579    {
580       // This should always fail:
581       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?");
582       return *this;
583    }
584    template <class Other>
operator /=boost::multiprecision::detail::expression585    BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
586    {
587       // This should always fail:
588       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?");
589       return *this;
590    }
591    template <class Other>
operator %=boost::multiprecision::detail::expression592    BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
593    {
594       // This should always fail:
595       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?");
596       return *this;
597    }
598    template <class Other>
operator |=boost::multiprecision::detail::expression599    BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
600    {
601       // This should always fail:
602       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?");
603       return *this;
604    }
605    template <class Other>
operator &=boost::multiprecision::detail::expression606    BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
607    {
608       // This should always fail:
609       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?");
610       return *this;
611    }
612    template <class Other>
operator ^=boost::multiprecision::detail::expression613    BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
614    {
615       // This should always fail:
616       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?");
617       return *this;
618    }
619    template <class Other>
operator <<=boost::multiprecision::detail::expression620    BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
621    {
622       // This should always fail:
623       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?");
624       return *this;
625    }
626    template <class Other>
operator >>=boost::multiprecision::detail::expression627    BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
628    {
629       // This should always fail:
630       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?");
631       return *this;
632    }
633 #endif
634 
leftboost::multiprecision::detail::expression635    BOOST_MP_CXX14_CONSTEXPR left_type left() const
636    {
637       return left_type(arg);
638    }
639 
left_refboost::multiprecision::detail::expression640    BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg; }
641 
642    static const unsigned depth = left_type::depth + 1;
643 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
644 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
645    //
646    // Horrible workaround for gcc-4.6.x which always prefers the template
647    // operator bool() rather than the non-template operator when converting to
648    // an arithmetic type:
649    //
650    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression651    explicit operator T() const
652    {
653       result_type r(*this);
654       return static_cast<bool>(r);
655    }
656    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression657    explicit operator T() const
658    {
659       return static_cast<T>(static_cast<result_type>(*this));
660    }
661 #else
662    template <class T
663 #ifndef __SUNPRO_CC
664              ,
665              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
666 #endif
667              >
operator Tboost::multiprecision::detail::expression668    explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
669    {
670       return static_cast<T>(static_cast<result_type>(*this));
671    }
operator boolboost::multiprecision::detail::expression672    BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
673    {
674       result_type r(*this);
675       return static_cast<bool>(r);
676    }
677 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression678    BOOST_MP_FORCEINLINE explicit operator void() const
679    {}
680 #endif
681 #endif
682 #else
operator unmentionable_typeboost::multiprecision::detail::expression683    operator unmentionable_type() const
684    {
685       result_type r(*this);
686       return r ? &unmentionable::proc : 0;
687    }
688 #endif
689 
690    template <class T>
convert_toboost::multiprecision::detail::expression691    BOOST_MP_CXX14_CONSTEXPR T convert_to()
692    {
693       result_type r(*this);
694       return r.template convert_to<T>();
695    }
696 
697  private:
698    typename expression_storage<Arg1>::type arg;
699    expression&                             operator=(const expression&);
700 };
701 
702 template <class Arg1>
703 struct expression<terminal, Arg1, void, void, void>
704 {
705    typedef mpl::int_<0> arity;
706    typedef Arg1         result_type;
707    typedef terminal     tag_type;
708 
expressionboost::multiprecision::detail::expression709    explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
expressionboost::multiprecision::detail::expression710    BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
711 
712 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
713    //
714    // If we have static_assert we can give a more useful error message
715    // than if we simply have no operator defined at all:
716    //
717    template <class Other>
operator =boost::multiprecision::detail::expression718    BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
719    {
720       // This should always fail:
721       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?");
722       return *this;
723    }
operator ++boost::multiprecision::detail::expression724    BOOST_MP_CXX14_CONSTEXPR expression& operator++()
725    {
726       // This should always fail:
727       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?");
728       return *this;
729    }
operator ++boost::multiprecision::detail::expression730    BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
731    {
732       // This should always fail:
733       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?");
734       return *this;
735    }
operator --boost::multiprecision::detail::expression736    BOOST_MP_CXX14_CONSTEXPR expression& operator--()
737    {
738       // This should always fail:
739       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?");
740       return *this;
741    }
operator --boost::multiprecision::detail::expression742    BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
743    {
744       // This should always fail:
745       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?");
746       return *this;
747    }
748    template <class Other>
operator +=boost::multiprecision::detail::expression749    BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
750    {
751       // This should always fail:
752       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?");
753       return *this;
754    }
755    template <class Other>
operator -=boost::multiprecision::detail::expression756    BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
757    {
758       // This should always fail:
759       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?");
760       return *this;
761    }
762    template <class Other>
operator *=boost::multiprecision::detail::expression763    BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
764    {
765       // This should always fail:
766       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?");
767       return *this;
768    }
769    template <class Other>
operator /=boost::multiprecision::detail::expression770    BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
771    {
772       // This should always fail:
773       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?");
774       return *this;
775    }
776    template <class Other>
operator %=boost::multiprecision::detail::expression777    BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
778    {
779       // This should always fail:
780       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?");
781       return *this;
782    }
783    template <class Other>
operator |=boost::multiprecision::detail::expression784    BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
785    {
786       // This should always fail:
787       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?");
788       return *this;
789    }
790    template <class Other>
operator &=boost::multiprecision::detail::expression791    BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
792    {
793       // This should always fail:
794       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?");
795       return *this;
796    }
797    template <class Other>
operator ^=boost::multiprecision::detail::expression798    BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
799    {
800       // This should always fail:
801       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?");
802       return *this;
803    }
804    template <class Other>
operator <<=boost::multiprecision::detail::expression805    BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
806    {
807       // This should always fail:
808       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?");
809       return *this;
810    }
811    template <class Other>
operator >>=boost::multiprecision::detail::expression812    BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
813    {
814       // This should always fail:
815       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?");
816       return *this;
817    }
818 #endif
819 
valueboost::multiprecision::detail::expression820    BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const BOOST_NOEXCEPT
821    {
822       return arg;
823    }
824 
825    static const unsigned depth = 0;
826 
827 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
828 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
829    //
830    // Horrible workaround for gcc-4.6.x which always prefers the template
831    // operator bool() rather than the non-template operator when converting to
832    // an arithmetic type:
833    //
834    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression835    explicit operator T() const
836    {
837       result_type r(*this);
838       return static_cast<bool>(r);
839    }
840    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression841    explicit operator T() const
842    {
843       return static_cast<T>(static_cast<result_type>(*this));
844    }
845 #else
846    template <class T
847 #ifndef __SUNPRO_CC
848              ,
849              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
850 #endif
851              >
operator Tboost::multiprecision::detail::expression852    explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
853    {
854       return static_cast<T>(static_cast<result_type>(*this));
855    }
operator boolboost::multiprecision::detail::expression856    BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
857    {
858       result_type r(*this);
859       return static_cast<bool>(r);
860    }
861 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression862    BOOST_MP_FORCEINLINE explicit operator void() const
863    {}
864 #endif
865 #endif
866 #else
operator unmentionable_typeboost::multiprecision::detail::expression867    operator unmentionable_type() const
868    {
869       return arg ? &unmentionable::proc : 0;
870    }
871 #endif
872 
873    template <class T>
convert_toboost::multiprecision::detail::expression874    BOOST_MP_CXX14_CONSTEXPR T convert_to()
875    {
876       result_type r(*this);
877       return r.template convert_to<T>();
878    }
879 
880  private:
881    typename expression_storage<Arg1>::type arg;
882    expression&                             operator=(const expression&);
883 };
884 
885 template <class tag, class Arg1, class Arg2>
886 struct expression<tag, Arg1, Arg2, void, void>
887 {
888    typedef mpl::int_<2>                                                           arity;
889    typedef typename arg_type<Arg1>::type                                          left_type;
890    typedef typename arg_type<Arg2>::type                                          right_type;
891    typedef typename left_type::result_type                                        left_result_type;
892    typedef typename right_type::result_type                                       right_result_type;
893    typedef typename combine_expression<left_result_type, right_result_type>::type result_type;
894    typedef tag                                                                    tag_type;
895 
expressionboost::multiprecision::detail::expression896    BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
expressionboost::multiprecision::detail::expression897    BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
898 
899 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
900    //
901    // If we have static_assert we can give a more useful error message
902    // than if we simply have no operator defined at all:
903    //
904    template <class Other>
operator =boost::multiprecision::detail::expression905    BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
906    {
907       // This should always fail:
908       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?");
909       return *this;
910    }
operator ++boost::multiprecision::detail::expression911    BOOST_MP_CXX14_CONSTEXPR expression& operator++()
912    {
913       // This should always fail:
914       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?");
915       return *this;
916    }
operator ++boost::multiprecision::detail::expression917    BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
918    {
919       // This should always fail:
920       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?");
921       return *this;
922    }
operator --boost::multiprecision::detail::expression923    BOOST_MP_CXX14_CONSTEXPR expression& operator--()
924    {
925       // This should always fail:
926       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?");
927       return *this;
928    }
operator --boost::multiprecision::detail::expression929    BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
930    {
931       // This should always fail:
932       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?");
933       return *this;
934    }
935    template <class Other>
operator +=boost::multiprecision::detail::expression936    BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
937    {
938       // This should always fail:
939       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?");
940       return *this;
941    }
942    template <class Other>
operator -=boost::multiprecision::detail::expression943    BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
944    {
945       // This should always fail:
946       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?");
947       return *this;
948    }
949    template <class Other>
operator *=boost::multiprecision::detail::expression950    BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
951    {
952       // This should always fail:
953       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?");
954       return *this;
955    }
956    template <class Other>
operator /=boost::multiprecision::detail::expression957    BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
958    {
959       // This should always fail:
960       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?");
961       return *this;
962    }
963    template <class Other>
operator %=boost::multiprecision::detail::expression964    BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
965    {
966       // This should always fail:
967       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?");
968       return *this;
969    }
970    template <class Other>
operator |=boost::multiprecision::detail::expression971    BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
972    {
973       // This should always fail:
974       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?");
975       return *this;
976    }
977    template <class Other>
operator &=boost::multiprecision::detail::expression978    BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
979    {
980       // This should always fail:
981       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?");
982       return *this;
983    }
984    template <class Other>
operator ^=boost::multiprecision::detail::expression985    BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
986    {
987       // This should always fail:
988       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?");
989       return *this;
990    }
991    template <class Other>
operator <<=boost::multiprecision::detail::expression992    BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
993    {
994       // This should always fail:
995       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?");
996       return *this;
997    }
998    template <class Other>
operator >>=boost::multiprecision::detail::expression999    BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1000    {
1001       // This should always fail:
1002       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?");
1003       return *this;
1004    }
1005 #endif
1006 
leftboost::multiprecision::detail::expression1007    BOOST_MP_CXX14_CONSTEXPR left_type left() const
1008    {
1009       return left_type(arg1);
1010    }
rightboost::multiprecision::detail::expression1011    BOOST_MP_CXX14_CONSTEXPR right_type  right() const { return right_type(arg2); }
left_refboost::multiprecision::detail::expression1012    BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
right_refboost::multiprecision::detail::expression1013    BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const BOOST_NOEXCEPT { return arg2; }
1014 
1015 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1016 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1017    //
1018    // Horrible workaround for gcc-4.6.x which always prefers the template
1019    // operator bool() rather than the non-template operator when converting to
1020    // an arithmetic type:
1021    //
1022    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1023    explicit operator T() const
1024    {
1025       result_type r(*this);
1026       return static_cast<bool>(r);
1027    }
1028    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression1029    explicit operator T() const
1030    {
1031       return static_cast<T>(static_cast<result_type>(*this));
1032    }
1033 #else
1034    template <class T
1035 #ifndef __SUNPRO_CC
1036              ,
1037              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
1038 #endif
1039              >
operator Tboost::multiprecision::detail::expression1040    explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1041    {
1042       return static_cast<T>(static_cast<result_type>(*this));
1043    }
operator boolboost::multiprecision::detail::expression1044    BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1045    {
1046       result_type r(*this);
1047       return static_cast<bool>(r);
1048    }
1049 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1050    BOOST_MP_FORCEINLINE explicit operator void() const
1051    {}
1052 #endif
1053 #endif
1054 #else
operator unmentionable_typeboost::multiprecision::detail::expression1055    operator unmentionable_type() const
1056    {
1057       result_type r(*this);
1058       return r ? &unmentionable::proc : 0;
1059    }
1060 #endif
1061    template <class T>
convert_toboost::multiprecision::detail::expression1062    BOOST_MP_CXX14_CONSTEXPR T convert_to()
1063    {
1064       result_type r(*this);
1065       return r.template convert_to<T>();
1066    }
1067 
1068    static const BOOST_MP_CXX14_CONSTEXPR unsigned left_depth  = left_type::depth + 1;
1069    static const BOOST_MP_CXX14_CONSTEXPR unsigned right_depth = right_type::depth + 1;
1070    static const BOOST_MP_CXX14_CONSTEXPR unsigned depth       = left_depth > right_depth ? left_depth : right_depth;
1071 
1072  private:
1073    typename expression_storage<Arg1>::type arg1;
1074    typename expression_storage<Arg2>::type arg2;
1075    expression&                             operator=(const expression&);
1076 };
1077 
1078 template <class tag, class Arg1, class Arg2, class Arg3>
1079 struct expression<tag, Arg1, Arg2, Arg3, void>
1080 {
1081    typedef mpl::int_<3>                      arity;
1082    typedef typename arg_type<Arg1>::type     left_type;
1083    typedef typename arg_type<Arg2>::type     middle_type;
1084    typedef typename arg_type<Arg3>::type     right_type;
1085    typedef typename left_type::result_type   left_result_type;
1086    typedef typename middle_type::result_type middle_result_type;
1087    typedef typename right_type::result_type  right_result_type;
1088    typedef typename combine_expression<
1089        left_result_type,
1090        typename combine_expression<right_result_type, middle_result_type>::type>::type result_type;
1091    typedef tag                                                                         tag_type;
1092 
expressionboost::multiprecision::detail::expression1093    BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
expressionboost::multiprecision::detail::expression1094    BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
1095 
1096 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1097    //
1098    // If we have static_assert we can give a more useful error message
1099    // than if we simply have no operator defined at all:
1100    //
1101    template <class Other>
operator =boost::multiprecision::detail::expression1102    BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1103    {
1104       // This should always fail:
1105       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?");
1106       return *this;
1107    }
operator ++boost::multiprecision::detail::expression1108    BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1109    {
1110       // This should always fail:
1111       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?");
1112       return *this;
1113    }
operator ++boost::multiprecision::detail::expression1114    BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1115    {
1116       // This should always fail:
1117       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?");
1118       return *this;
1119    }
operator --boost::multiprecision::detail::expression1120    BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1121    {
1122       // This should always fail:
1123       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?");
1124       return *this;
1125    }
operator --boost::multiprecision::detail::expression1126    BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1127    {
1128       // This should always fail:
1129       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?");
1130       return *this;
1131    }
1132    template <class Other>
operator +=boost::multiprecision::detail::expression1133    BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1134    {
1135       // This should always fail:
1136       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?");
1137       return *this;
1138    }
1139    template <class Other>
operator -=boost::multiprecision::detail::expression1140    BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1141    {
1142       // This should always fail:
1143       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?");
1144       return *this;
1145    }
1146    template <class Other>
operator *=boost::multiprecision::detail::expression1147    BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1148    {
1149       // This should always fail:
1150       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?");
1151       return *this;
1152    }
1153    template <class Other>
operator /=boost::multiprecision::detail::expression1154    BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1155    {
1156       // This should always fail:
1157       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?");
1158       return *this;
1159    }
1160    template <class Other>
operator %=boost::multiprecision::detail::expression1161    BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1162    {
1163       // This should always fail:
1164       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?");
1165       return *this;
1166    }
1167    template <class Other>
operator |=boost::multiprecision::detail::expression1168    BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1169    {
1170       // This should always fail:
1171       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?");
1172       return *this;
1173    }
1174    template <class Other>
operator &=boost::multiprecision::detail::expression1175    BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1176    {
1177       // This should always fail:
1178       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?");
1179       return *this;
1180    }
1181    template <class Other>
operator ^=boost::multiprecision::detail::expression1182    BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1183    {
1184       // This should always fail:
1185       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?");
1186       return *this;
1187    }
1188    template <class Other>
operator <<=boost::multiprecision::detail::expression1189    BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1190    {
1191       // This should always fail:
1192       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?");
1193       return *this;
1194    }
1195    template <class Other>
operator >>=boost::multiprecision::detail::expression1196    BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1197    {
1198       // This should always fail:
1199       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?");
1200       return *this;
1201    }
1202 #endif
1203 
leftboost::multiprecision::detail::expression1204    BOOST_MP_CXX14_CONSTEXPR left_type left() const
1205    {
1206       return left_type(arg1);
1207    }
middleboost::multiprecision::detail::expression1208    BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
rightboost::multiprecision::detail::expression1209    BOOST_MP_CXX14_CONSTEXPR right_type  right() const { return right_type(arg3); }
left_refboost::multiprecision::detail::expression1210    BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
middle_refboost::multiprecision::detail::expression1211    BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const BOOST_NOEXCEPT { return arg2; }
right_refboost::multiprecision::detail::expression1212    BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const BOOST_NOEXCEPT { return arg3; }
1213 
1214 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1215 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1216    //
1217    // Horrible workaround for gcc-4.6.x which always prefers the template
1218    // operator bool() rather than the non-template operator when converting to
1219    // an arithmetic type:
1220    //
1221    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1222    explicit operator T() const
1223    {
1224       result_type r(*this);
1225       return static_cast<bool>(r);
1226    }
1227    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression1228    explicit operator T() const
1229    {
1230       return static_cast<T>(static_cast<result_type>(*this));
1231    }
1232 #else
1233    template <class T
1234 #ifndef __SUNPRO_CC
1235              ,
1236              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
1237 #endif
1238              >
operator Tboost::multiprecision::detail::expression1239    explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1240    {
1241       return static_cast<T>(static_cast<result_type>(*this));
1242    }
operator boolboost::multiprecision::detail::expression1243    BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1244    {
1245       result_type r(*this);
1246       return static_cast<bool>(r);
1247    }
1248 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1249    BOOST_MP_FORCEINLINE explicit operator void() const
1250    {}
1251 #endif
1252 #endif
1253 #else
operator unmentionable_typeboost::multiprecision::detail::expression1254    operator unmentionable_type() const
1255    {
1256       result_type r(*this);
1257       return r ? &unmentionable::proc : 0;
1258    }
1259 #endif
1260    template <class T>
convert_toboost::multiprecision::detail::expression1261    BOOST_MP_CXX14_CONSTEXPR T convert_to()
1262    {
1263       result_type r(*this);
1264       return r.template convert_to<T>();
1265    }
1266 
1267    static const unsigned left_depth   = left_type::depth + 1;
1268    static const unsigned middle_depth = middle_type::depth + 1;
1269    static const unsigned right_depth  = right_type::depth + 1;
1270    static const unsigned depth        = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
1271 
1272  private:
1273    typename expression_storage<Arg1>::type arg1;
1274    typename expression_storage<Arg2>::type arg2;
1275    typename expression_storage<Arg3>::type arg3;
1276    expression&                             operator=(const expression&);
1277 };
1278 
1279 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1280 struct expression
1281 {
1282    typedef mpl::int_<4>                            arity;
1283    typedef typename arg_type<Arg1>::type           left_type;
1284    typedef typename arg_type<Arg2>::type           left_middle_type;
1285    typedef typename arg_type<Arg3>::type           right_middle_type;
1286    typedef typename arg_type<Arg4>::type           right_type;
1287    typedef typename left_type::result_type         left_result_type;
1288    typedef typename left_middle_type::result_type  left_middle_result_type;
1289    typedef typename right_middle_type::result_type right_middle_result_type;
1290    typedef typename right_type::result_type        right_result_type;
1291    typedef typename combine_expression<
1292        left_result_type,
1293        typename combine_expression<
1294            left_middle_result_type,
1295            typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type result_type;
1296    typedef tag                                                                                          tag_type;
1297 
expressionboost::multiprecision::detail::expression1298    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) {}
expressionboost::multiprecision::detail::expression1299    BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
1300 
1301 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1302    //
1303    // If we have static_assert we can give a more useful error message
1304    // than if we simply have no operator defined at all:
1305    //
1306    template <class Other>
operator =boost::multiprecision::detail::expression1307    BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1308    {
1309       // This should always fail:
1310       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?");
1311       return *this;
1312    }
operator ++boost::multiprecision::detail::expression1313    BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1314    {
1315       // This should always fail:
1316       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?");
1317       return *this;
1318    }
operator ++boost::multiprecision::detail::expression1319    BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1320    {
1321       // This should always fail:
1322       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?");
1323       return *this;
1324    }
operator --boost::multiprecision::detail::expression1325    BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1326    {
1327       // This should always fail:
1328       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?");
1329       return *this;
1330    }
operator --boost::multiprecision::detail::expression1331    BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1332    {
1333       // This should always fail:
1334       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?");
1335       return *this;
1336    }
1337    template <class Other>
operator +=boost::multiprecision::detail::expression1338    BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1339    {
1340       // This should always fail:
1341       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?");
1342       return *this;
1343    }
1344    template <class Other>
operator -=boost::multiprecision::detail::expression1345    BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1346    {
1347       // This should always fail:
1348       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?");
1349       return *this;
1350    }
1351    template <class Other>
operator *=boost::multiprecision::detail::expression1352    BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1353    {
1354       // This should always fail:
1355       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?");
1356       return *this;
1357    }
1358    template <class Other>
operator /=boost::multiprecision::detail::expression1359    BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1360    {
1361       // This should always fail:
1362       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?");
1363       return *this;
1364    }
1365    template <class Other>
operator %=boost::multiprecision::detail::expression1366    BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1367    {
1368       // This should always fail:
1369       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?");
1370       return *this;
1371    }
1372    template <class Other>
operator |=boost::multiprecision::detail::expression1373    BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1374    {
1375       // This should always fail:
1376       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?");
1377       return *this;
1378    }
1379    template <class Other>
operator &=boost::multiprecision::detail::expression1380    BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1381    {
1382       // This should always fail:
1383       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?");
1384       return *this;
1385    }
1386    template <class Other>
operator ^=boost::multiprecision::detail::expression1387    BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1388    {
1389       // This should always fail:
1390       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?");
1391       return *this;
1392    }
1393    template <class Other>
operator <<=boost::multiprecision::detail::expression1394    BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1395    {
1396       // This should always fail:
1397       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?");
1398       return *this;
1399    }
1400    template <class Other>
operator >>=boost::multiprecision::detail::expression1401    BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1402    {
1403       // This should always fail:
1404       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?");
1405       return *this;
1406    }
1407 #endif
1408 
leftboost::multiprecision::detail::expression1409    BOOST_MP_CXX14_CONSTEXPR left_type left() const
1410    {
1411       return left_type(arg1);
1412    }
left_middleboost::multiprecision::detail::expression1413    BOOST_MP_CXX14_CONSTEXPR left_middle_type  left_middle() const { return left_middle_type(arg2); }
right_middleboost::multiprecision::detail::expression1414    BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
rightboost::multiprecision::detail::expression1415    BOOST_MP_CXX14_CONSTEXPR right_type        right() const { return right_type(arg4); }
left_refboost::multiprecision::detail::expression1416    BOOST_MP_CXX14_CONSTEXPR const Arg1&       left_ref() const BOOST_NOEXCEPT { return arg1; }
left_middle_refboost::multiprecision::detail::expression1417    BOOST_MP_CXX14_CONSTEXPR const Arg2&       left_middle_ref() const BOOST_NOEXCEPT { return arg2; }
right_middle_refboost::multiprecision::detail::expression1418    BOOST_MP_CXX14_CONSTEXPR const Arg3&       right_middle_ref() const BOOST_NOEXCEPT { return arg3; }
right_refboost::multiprecision::detail::expression1419    BOOST_MP_CXX14_CONSTEXPR const Arg4&       right_ref() const BOOST_NOEXCEPT { return arg4; }
1420 
1421 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1422 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1423    //
1424    // Horrible workaround for gcc-4.6.x which always prefers the template
1425    // operator bool() rather than the non-template operator when converting to
1426    // an arithmetic type:
1427    //
1428    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1429    explicit operator T() const
1430    {
1431       result_type r(*this);
1432       return static_cast<bool>(r);
1433    }
1434    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression1435    explicit operator T() const
1436    {
1437       return static_cast<T>(static_cast<result_type>(*this));
1438    }
1439 #else
1440    template <class T
1441 #ifndef __SUNPRO_CC
1442              ,
1443              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
1444 #endif
1445              >
operator Tboost::multiprecision::detail::expression1446    explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1447    {
1448       return static_cast<T>(static_cast<result_type>(*this));
1449    }
operator boolboost::multiprecision::detail::expression1450    BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1451    {
1452       result_type r(*this);
1453       return static_cast<bool>(r);
1454    }
1455 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1456    BOOST_MP_FORCEINLINE explicit operator void() const
1457    {}
1458 #endif
1459 #endif
1460 #else
operator unmentionable_typeboost::multiprecision::detail::expression1461    operator unmentionable_type() const
1462    {
1463       result_type r(*this);
1464       return r ? &unmentionable::proc : 0;
1465    }
1466 #endif
1467    template <class T>
convert_toboost::multiprecision::detail::expression1468    BOOST_MP_CXX14_CONSTEXPR T convert_to()
1469    {
1470       result_type r(*this);
1471       return r.template convert_to<T>();
1472    }
1473 
1474    static const unsigned left_depth         = left_type::depth + 1;
1475    static const unsigned left_middle_depth  = left_middle_type::depth + 1;
1476    static const unsigned right_middle_depth = right_middle_type::depth + 1;
1477    static const unsigned right_depth        = right_type::depth + 1;
1478 
1479    static const unsigned left_max_depth  = left_depth > left_middle_depth ? left_depth : left_middle_depth;
1480    static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
1481 
1482    static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
1483 
1484  private:
1485    typename expression_storage<Arg1>::type arg1;
1486    typename expression_storage<Arg2>::type arg2;
1487    typename expression_storage<Arg3>::type arg3;
1488    typename expression_storage<Arg4>::type arg4;
1489    expression&                             operator=(const expression&);
1490 };
1491 
1492 template <class T>
1493 struct digits2
1494 {
1495    BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
1496    BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
1497    // If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
1498    BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
1499    static const long                  m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
valueboost::multiprecision::detail::digits21500    static inline BOOST_CONSTEXPR long value() BOOST_NOEXCEPT { return m_value; }
1501 };
1502 
1503 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
1504 #ifdef _MSC_VER
1505 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1506 #else
1507 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1508 #endif
1509 #endif
1510 
1511 template <class S>
format_float_string(S & str,boost::intmax_t my_exp,boost::intmax_t digits,std::ios_base::fmtflags f,bool iszero)1512 void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
1513 {
1514    typedef typename S::size_type size_type;
1515    bool                          scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
1516    bool                          fixed      = (f & std::ios_base::fixed) == std::ios_base::fixed;
1517    bool                          showpoint  = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
1518    bool                          showpos    = (f & std::ios_base::showpos) == std::ios_base::showpos;
1519 
1520    bool neg = str.size() && (str[0] == '-');
1521 
1522    if (neg)
1523       str.erase(0, 1);
1524 
1525    if (digits == 0)
1526    {
1527       digits = (std::max)(str.size(), size_type(16));
1528    }
1529 
1530    if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
1531    {
1532       // We will be printing zero, even though the value might not
1533       // actually be zero (it just may have been rounded to zero).
1534       str = "0";
1535       if (scientific || fixed)
1536       {
1537          str.append(1, '.');
1538          str.append(size_type(digits), '0');
1539          if (scientific)
1540             str.append("e+00");
1541       }
1542       else
1543       {
1544          if (showpoint)
1545          {
1546             str.append(1, '.');
1547             if (digits > 1)
1548                str.append(size_type(digits - 1), '0');
1549          }
1550       }
1551       if (neg)
1552          str.insert(static_cast<std::string::size_type>(0), 1, '-');
1553       else if (showpos)
1554          str.insert(static_cast<std::string::size_type>(0), 1, '+');
1555       return;
1556    }
1557 
1558    if (!fixed && !scientific && !showpoint)
1559    {
1560       //
1561       // Suppress trailing zeros:
1562       //
1563       std::string::iterator pos = str.end();
1564       while (pos != str.begin() && *--pos == '0')
1565       {
1566       }
1567       if (pos != str.end())
1568          ++pos;
1569       str.erase(pos, str.end());
1570       if (str.empty())
1571          str = '0';
1572    }
1573    else if (!fixed || (my_exp >= 0))
1574    {
1575       //
1576       // Pad out the end with zero's if we need to:
1577       //
1578       boost::intmax_t chars = str.size();
1579       chars                 = digits - chars;
1580       if (scientific)
1581          ++chars;
1582       if (chars > 0)
1583       {
1584          str.append(static_cast<std::string::size_type>(chars), '0');
1585       }
1586    }
1587 
1588    if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
1589    {
1590       if (1 + my_exp > static_cast<boost::intmax_t>(str.size()))
1591       {
1592          // Just pad out the end with zeros:
1593          str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
1594          if (showpoint || fixed)
1595             str.append(".");
1596       }
1597       else if (my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
1598       {
1599          if (my_exp < 0)
1600          {
1601             str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
1602             str.insert(static_cast<std::string::size_type>(0), "0.");
1603          }
1604          else
1605          {
1606             // Insert the decimal point:
1607             str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
1608          }
1609       }
1610       else if (showpoint || fixed) // we have exactly the digits we require to left of the point
1611          str += ".";
1612 
1613       if (fixed)
1614       {
1615          // We may need to add trailing zeros:
1616          boost::intmax_t l = str.find('.') + 1;
1617          l                 = digits - (str.size() - l);
1618          if (l > 0)
1619             str.append(size_type(l), '0');
1620       }
1621    }
1622    else
1623    {
1624       BOOST_MP_USING_ABS
1625       // Scientific format:
1626       if (showpoint || (str.size() > 1))
1627          str.insert(static_cast<std::string::size_type>(1u), 1, '.');
1628       str.append(static_cast<std::string::size_type>(1u), 'e');
1629       S e = boost::lexical_cast<S>(abs(my_exp));
1630       if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
1631          e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
1632       if (my_exp < 0)
1633          e.insert(static_cast<std::string::size_type>(0), 1, '-');
1634       else
1635          e.insert(static_cast<std::string::size_type>(0), 1, '+');
1636       str.append(e);
1637    }
1638    if (neg)
1639       str.insert(static_cast<std::string::size_type>(0), 1, '-');
1640    else if (showpos)
1641       str.insert(static_cast<std::string::size_type>(0), 1, '+');
1642 }
1643 
1644 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::true_ &)1645 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
1646 {
1647    if (val > (std::numeric_limits<std::size_t>::max)())
1648       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1649    if (val < 0)
1650       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1651 }
1652 template <class V>
check_shift_range(V val,const mpl::false_ &,const mpl::true_ &)1653 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
1654 {
1655    if (val < 0)
1656       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1657 }
1658 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::false_ &)1659 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
1660 {
1661    if (val > (std::numeric_limits<std::size_t>::max)())
1662       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1663 }
1664 template <class V>
check_shift_range(V,const mpl::false_ &,const mpl::false_ &)1665 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT {}
1666 
1667 template <class T>
evaluate_if_expression(const T & val)1668 BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
1669 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
evaluate_if_expression(const expression<tag,Arg1,Arg2,Arg3,Arg4> & val)1670 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; }
1671 
1672 } // namespace detail
1673 
1674 //
1675 // Traits class, lets us know what kind of number we have, defaults to a floating point type:
1676 //
1677 enum number_category_type
1678 {
1679    number_kind_unknown        = -1,
1680    number_kind_integer        = 0,
1681    number_kind_floating_point = 1,
1682    number_kind_rational       = 2,
1683    number_kind_fixed_point    = 3,
1684    number_kind_complex        = 4
1685 };
1686 
1687 template <class Num, bool, bool>
1688 struct number_category_base : public mpl::int_<number_kind_unknown>
1689 {};
1690 template <class Num>
1691 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)>
1692 {};
1693 template <class Num>
1694 struct number_category : public number_category_base<Num, boost::is_class<Num>::value || boost::is_arithmetic<Num>::value, boost::is_abstract<Num>::value>
1695 {};
1696 template <class Backend, expression_template_option ExpressionTemplates>
1697 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
1698 {};
1699 template <class tag, class A1, class A2, class A3, class A4>
1700 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1701 {};
1702 //
1703 // Specializations for types which do not always have numberic_limits specializations:
1704 //
1705 #ifdef BOOST_HAS_INT128
1706 template <>
1707 struct number_category<boost::int128_type> : public mpl::int_<number_kind_integer>
1708 {};
1709 template <>
1710 struct number_category<boost::uint128_type> : public mpl::int_<number_kind_integer>
1711 {};
1712 #endif
1713 #ifdef BOOST_HAS_FLOAT128
1714 template <>
1715 struct number_category<__float128> : public mpl::int_<number_kind_floating_point>
1716 {};
1717 #endif
1718 
1719 template <class T>
1720 struct component_type
1721 {
1722    typedef T type;
1723 };
1724 template <class tag, class A1, class A2, class A3, class A4>
1725 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1726 {};
1727 
1728 template <class T>
1729 struct scalar_result_from_possible_complex
1730 {
1731    typedef typename mpl::if_c<number_category<T>::value == number_kind_complex,
1732                               typename component_type<T>::type, T>::type type;
1733 };
1734 
1735 template <class T>
1736 struct complex_result_from_scalar; // individual backends must specialize this trait.
1737 
1738 template <class T>
1739 struct is_unsigned_number : public mpl::false_
1740 {};
1741 template <class Backend, expression_template_option ExpressionTemplates>
1742 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
1743 {};
1744 template <class T>
1745 struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value>
1746 {};
1747 template <class T>
1748 struct is_interval_number : public mpl::false_
1749 {};
1750 template <class Backend, expression_template_option ExpressionTemplates>
1751 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
1752 {};
1753 
1754 } // namespace multiprecision
1755 } // namespace boost
1756 
1757 namespace boost { namespace math {
1758    namespace tools {
1759 
1760       template <class T>
1761       struct promote_arg;
1762 
1763       template <class tag, class A1, class A2, class A3, class A4>
1764       struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
1765       {
1766          typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
1767       };
1768 
1769       template <class R, class B, boost::multiprecision::expression_template_option ET>
real_cast(const boost::multiprecision::number<B,ET> & val)1770       inline R real_cast(const boost::multiprecision::number<B, ET>& val)
1771       {
1772          return val.template convert_to<R>();
1773       }
1774 
1775       template <class R, class tag, class A1, class A2, class A3, class A4>
real_cast(const boost::multiprecision::detail::expression<tag,A1,A2,A3,A4> & val)1776       inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
1777       {
1778          typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
1779          return val_type(val).template convert_to<R>();
1780       }
1781 
1782       template <class B, boost::multiprecision::expression_template_option ET>
1783       struct is_complex_type<boost::multiprecision::number<B, ET> > : public boost::mpl::bool_<boost::multiprecision::number_category<B>::value == boost::multiprecision::number_kind_complex> {};
1784 
1785 } // namespace tools
1786 
1787 namespace constants {
1788 
1789 template <class T>
1790 struct is_explicitly_convertible_from_string;
1791 
1792 template <class B, boost::multiprecision::expression_template_option ET>
1793 struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
1794 {
1795    static const bool value = true;
1796 };
1797 
1798 } // namespace constants
1799 
1800 }} // namespace boost::math
1801 
1802 #ifdef BOOST_MSVC
1803 #pragma warning(pop)
1804 #endif
1805 
1806 #endif // BOOST_MATH_BIG_NUM_BASE_HPP
1807