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(NDEBUG) && !defined(_DEBUG)
26 #define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE
27 #else
28 #define BOOST_MP_FORCEINLINE inline
29 #endif
30
31 #if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) || (defined(__clang_major__) && (__clang_major__ == 3) && (__clang_minor__ < 5))
32 #define BOOST_MP_NOEXCEPT_IF(x)
33 #else
34 #define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
35 #endif
36
37 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
38 #define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
39 #endif
40
41 //
42 // Thread local storage:
43 // Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
44 //
45 #if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__)
46 #define BOOST_MP_THREAD_LOCAL thread_local
47 #define BOOST_MP_USING_THREAD_LOCAL
48 #else
49 #define BOOST_MP_THREAD_LOCAL
50 #endif
51
52 // Workaround for Win/Mac VERSION
53 #if !defined(_WIN32) && !defined(__APPLE__)
54 // We may end up including our own VERSION file,
55 // because the file system ignores case.
56 // TODO: rename VERSION to something else.
57 #ifdef __has_include
58 # if __has_include(<version>)
59 # include <version>
60 # ifdef __cpp_lib_is_constant_evaluated
61 # include <type_traits>
62 # define BOOST_MP_HAS_IS_CONSTANT_EVALUATED
63 # endif
64 # endif
65 #endif
66 #endif // Workaround for Win/Mac VERSION
67
68 #ifdef __has_builtin
69 #if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
70 #define BOOST_MP_CLANG_CD
71 #endif
72 #endif
73
74 #if defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
75 # define BOOST_MP_IS_CONST_EVALUATED(x) std::is_constant_evaluated()
76 #elif (defined(BOOST_GCC) && !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9)) || defined(BOOST_MP_CLANG_CD)
77 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_is_constant_evaluated()
78 #elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_GCC) && (__GNUC__ >= 6)
79 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_constant_p(x)
80 #else
81 # define BOOST_MP_NO_CONSTEXPR_DETECTION
82 #endif
83
84 #define BOOST_MP_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
85
86 //
87 // Early compiler versions trip over the constexpr code:
88 //
89 #if defined(__clang__) && (__clang_major__ < 5)
90 #undef BOOST_MP_CXX14_CONSTEXPR
91 #define BOOST_MP_CXX14_CONSTEXPR
92 #endif
93 #if defined(__apple_build_version__) && (__clang_major__ < 9)
94 #undef BOOST_MP_CXX14_CONSTEXPR
95 #define BOOST_MP_CXX14_CONSTEXPR
96 #endif
97 #if defined(BOOST_GCC) && (__GNUC__ < 6)
98 #undef BOOST_MP_CXX14_CONSTEXPR
99 #define BOOST_MP_CXX14_CONSTEXPR
100 #endif
101
102 // Workaround for Sun Developer Studio 12.6
103 #if defined(__SUNPRO_CC)
104 #define BOOST_MP_NO_CONSTEXPR_DETECTION
105 #undef BOOST_MP_CXX14_CONSTEXPR
106 #define BOOST_MP_CXX14_CONSTEXPR
107 #endif
108
109 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
110 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION
111 #else
112 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION constexpr
113 #endif
114
115 #ifdef BOOST_MSVC
116 #pragma warning(push)
117 #pragma warning(disable : 6326)
118 #endif
119
120 namespace boost {
121 namespace multiprecision {
122
123 enum expression_template_option
124 {
125 et_off = 0,
126 et_on = 1
127 };
128
129 template <class Backend>
130 struct expression_template_default
131 {
132 static const expression_template_option value = et_on;
133 };
134
135 template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
136 class number;
137
138 template <class T>
139 struct is_number : public mpl::false_
140 {};
141
142 template <class Backend, expression_template_option ExpressionTemplates>
143 struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_
144 {};
145
146 template <class T>
147 struct is_et_number : public mpl::false_
148 {};
149
150 template <class Backend>
151 struct is_et_number<number<Backend, et_on> > : public mpl::true_
152 {};
153
154 template <class T>
155 struct is_no_et_number : public mpl::false_
156 {};
157
158 template <class Backend>
159 struct is_no_et_number<number<Backend, et_off> > : public mpl::true_
160 {};
161
162 namespace detail {
163
164 // Forward-declare an expression wrapper
165 template <class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
166 struct expression;
167
168 } // namespace detail
169
170 template <class T>
171 struct is_number_expression : public mpl::false_
172 {};
173
174 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
175 struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_
176 {};
177
178 template <class T, class Num>
179 struct is_compatible_arithmetic_type
180 : public mpl::bool_<
181 is_convertible<T, Num>::value && !is_same<T, Num>::value && !is_number_expression<T>::value>
182 {};
183
184 namespace detail {
185 //
186 // Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
187 //
188 template <class T>
abs(T t)189 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
190 {
191 // This strange expression avoids a hardware trap in the corner case
192 // that val is the most negative value permitted in boost::long_long_type.
193 // See https://svn.boost.org/trac/boost/ticket/9740.
194 return t < 0 ? T(1u) + T(-(t + 1)) : t;
195 }
196 template <class T>
abs(T t)197 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
198 {
199 return t;
200 }
201
202 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
203
204 template <class T>
unsigned_abs(T t)205 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
206 {
207 // This strange expression avoids a hardware trap in the corner case
208 // that val is the most negative value permitted in boost::long_long_type.
209 // See https://svn.boost.org/trac/boost/ticket/9740.
210 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);
211 }
212 template <class T>
unsigned_abs(T t)213 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
214 {
215 return t;
216 }
217
218 //
219 // Move support:
220 //
221 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
222 #define BOOST_MP_MOVE(x) std::move(x)
223 #else
224 #define BOOST_MP_MOVE(x) x
225 #endif
226
227 template <class T>
228 struct bits_of
229 {
230 BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
231 static const unsigned value =
232 std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
233 : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
234 };
235
236 #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
237 template <>
238 struct bits_of<__float128>
239 {
240 static const unsigned value = 113;
241 };
242 #endif
243
244 template <int b>
245 struct has_enough_bits
246 {
247 template <class T>
248 struct type : public mpl::bool_<bits_of<T>::value >= b>
249 {};
250 };
251
252 template <class Val, class Backend, class Tag>
253 struct canonical_imp
254 {
255 typedef typename remove_cv<typename decay<const Val>::type>::type type;
256 };
257 template <class B, class Backend, class Tag>
258 struct canonical_imp<number<B, et_on>, Backend, Tag>
259 {
260 typedef B type;
261 };
262 template <class B, class Backend, class Tag>
263 struct canonical_imp<number<B, et_off>, Backend, Tag>
264 {
265 typedef B type;
266 };
267 #ifdef __SUNPRO_CC
268 template <class B, class Backend>
269 struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
270 {
271 typedef B type;
272 };
273 template <class B, class Backend>
274 struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
275 {
276 typedef B type;
277 };
278 #endif
279 template <class Val, class Backend>
280 struct canonical_imp<Val, Backend, mpl::int_<0> >
281 {
282 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
283 typedef typename mpl::find_if<
284 typename Backend::signed_types,
285 pred_type>::type iter_type;
286 typedef typename mpl::end<typename Backend::signed_types>::type end_type;
287 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
288 };
289 template <class Val, class Backend>
290 struct canonical_imp<Val, Backend, mpl::int_<1> >
291 {
292 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
293 typedef typename mpl::find_if<
294 typename Backend::unsigned_types,
295 pred_type>::type iter_type;
296 typedef typename mpl::end<typename Backend::unsigned_types>::type end_type;
297 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
298 };
299 template <class Val, class Backend>
300 struct canonical_imp<Val, Backend, mpl::int_<2> >
301 {
302 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
303 typedef typename mpl::find_if<
304 typename Backend::float_types,
305 pred_type>::type iter_type;
306 typedef typename mpl::end<typename Backend::float_types>::type end_type;
307 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
308 };
309 template <class Val, class Backend>
310 struct canonical_imp<Val, Backend, mpl::int_<3> >
311 {
312 typedef const char* type;
313 };
314
315 template <class Val, class Backend>
316 struct canonical
317 {
318 typedef typename mpl::if_<
319 is_signed<Val>,
320 mpl::int_<0>,
321 typename mpl::if_<
322 is_unsigned<Val>,
323 mpl::int_<1>,
324 typename mpl::if_<
325 is_floating_point<Val>,
326 mpl::int_<2>,
327 typename mpl::if_<
328 mpl::or_<
329 is_convertible<Val, const char*>,
330 is_same<Val, std::string> >,
331 mpl::int_<3>,
332 mpl::int_<4> >::type>::type>::type>::type tag_type;
333
334 typedef typename canonical_imp<Val, Backend, tag_type>::type type;
335 };
336
337 struct terminal
338 {};
339 struct negate
340 {};
341 struct plus
342 {};
343 struct minus
344 {};
345 struct multiplies
346 {};
347 struct divides
348 {};
349 struct modulus
350 {};
351 struct shift_left
352 {};
353 struct shift_right
354 {};
355 struct bitwise_and
356 {};
357 struct bitwise_or
358 {};
359 struct bitwise_xor
360 {};
361 struct bitwise_complement
362 {};
363 struct add_immediates
364 {};
365 struct subtract_immediates
366 {};
367 struct multiply_immediates
368 {};
369 struct divide_immediates
370 {};
371 struct modulus_immediates
372 {};
373 struct bitwise_and_immediates
374 {};
375 struct bitwise_or_immediates
376 {};
377 struct bitwise_xor_immediates
378 {};
379 struct complement_immediates
380 {};
381 struct function
382 {};
383 struct multiply_add
384 {};
385 struct multiply_subtract
386 {};
387
388 template <class T>
389 struct backend_type;
390
391 template <class T, expression_template_option ExpressionTemplates>
392 struct backend_type<number<T, ExpressionTemplates> >
393 {
394 typedef T type;
395 };
396
397 template <class tag, class A1, class A2, class A3, class A4>
398 struct backend_type<expression<tag, A1, A2, A3, A4> >
399 {
400 typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
401 };
402
403 template <class T1, class T2>
404 struct combine_expression
405 {
406 #ifdef BOOST_NO_CXX11_DECLTYPE
407 typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
408 #else
409 typedef decltype(T1() + T2()) type;
410 #endif
411 };
412
413 template <class T1, expression_template_option ExpressionTemplates, class T2>
414 struct combine_expression<number<T1, ExpressionTemplates>, T2>
415 {
416 typedef number<T1, ExpressionTemplates> type;
417 };
418
419 template <class T1, class T2, expression_template_option ExpressionTemplates>
420 struct combine_expression<T1, number<T2, ExpressionTemplates> >
421 {
422 typedef number<T2, ExpressionTemplates> type;
423 };
424
425 template <class T, expression_template_option ExpressionTemplates>
426 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
427 {
428 typedef number<T, ExpressionTemplates> type;
429 };
430
431 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
432 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
433 {
434 typedef typename mpl::if_c<
435 is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
436 number<T1, ExpressionTemplates1>,
437 number<T2, ExpressionTemplates2> >::type type;
438 };
439
440 template <class T>
441 struct arg_type
442 {
443 typedef expression<terminal, T> type;
444 };
445
446 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
447 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
448 {
449 typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
450 };
451
452 struct unmentionable
453 {
procboost::multiprecision::detail::unmentionable454 unmentionable* proc() { return 0; }
455 };
456
457 typedef unmentionable* (unmentionable::*unmentionable_type)();
458
459 template <class T, bool b>
460 struct expression_storage_base
461 {
462 typedef const T& type;
463 };
464
465 template <class T>
466 struct expression_storage_base<T, true>
467 {
468 typedef T type;
469 };
470
471 template <class T>
472 struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value>
473 {};
474
475 template <class T>
476 struct expression_storage<T*>
477 {
478 typedef T* type;
479 };
480
481 template <class T>
482 struct expression_storage<const T*>
483 {
484 typedef const T* type;
485 };
486
487 template <class tag, class A1, class A2, class A3, class A4>
488 struct expression_storage<expression<tag, A1, A2, A3, A4> >
489 {
490 typedef expression<tag, A1, A2, A3, A4> type;
491 };
492
493 template <class tag, class Arg1>
494 struct expression<tag, Arg1, void, void, void>
495 {
496 typedef mpl::int_<1> arity;
497 typedef typename arg_type<Arg1>::type left_type;
498 typedef typename left_type::result_type left_result_type;
499 typedef typename left_type::result_type result_type;
500 typedef tag tag_type;
501
expressionboost::multiprecision::detail::expression502 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
expressionboost::multiprecision::detail::expression503 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
504
505 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
506 //
507 // If we have static_assert we can give a more useful error message
508 // than if we simply have no operator defined at all:
509 //
510 template <class Other>
operator =boost::multiprecision::detail::expression511 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
512 {
513 // This should always fail:
514 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?");
515 return *this;
516 }
operator ++boost::multiprecision::detail::expression517 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
518 {
519 // This should always fail:
520 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?");
521 return *this;
522 }
operator ++boost::multiprecision::detail::expression523 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
524 {
525 // This should always fail:
526 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?");
527 return *this;
528 }
operator --boost::multiprecision::detail::expression529 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
530 {
531 // This should always fail:
532 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?");
533 return *this;
534 }
operator --boost::multiprecision::detail::expression535 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
536 {
537 // This should always fail:
538 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?");
539 return *this;
540 }
541 template <class Other>
operator +=boost::multiprecision::detail::expression542 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
543 {
544 // This should always fail:
545 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
546 return *this;
547 }
548 template <class Other>
operator -=boost::multiprecision::detail::expression549 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
550 {
551 // This should always fail:
552 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
553 return *this;
554 }
555 template <class Other>
operator *=boost::multiprecision::detail::expression556 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
557 {
558 // This should always fail:
559 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
560 return *this;
561 }
562 template <class Other>
operator /=boost::multiprecision::detail::expression563 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
564 {
565 // This should always fail:
566 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
567 return *this;
568 }
569 template <class Other>
operator %=boost::multiprecision::detail::expression570 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
571 {
572 // This should always fail:
573 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
574 return *this;
575 }
576 template <class Other>
operator |=boost::multiprecision::detail::expression577 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
578 {
579 // This should always fail:
580 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
581 return *this;
582 }
583 template <class Other>
operator &=boost::multiprecision::detail::expression584 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
585 {
586 // This should always fail:
587 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
588 return *this;
589 }
590 template <class Other>
operator ^=boost::multiprecision::detail::expression591 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
592 {
593 // This should always fail:
594 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
595 return *this;
596 }
597 template <class Other>
operator <<=boost::multiprecision::detail::expression598 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
599 {
600 // This should always fail:
601 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?");
602 return *this;
603 }
604 template <class Other>
operator >>=boost::multiprecision::detail::expression605 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
606 {
607 // This should always fail:
608 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?");
609 return *this;
610 }
611 #endif
612
leftboost::multiprecision::detail::expression613 BOOST_MP_CXX14_CONSTEXPR left_type left() const
614 {
615 return left_type(arg);
616 }
617
left_refboost::multiprecision::detail::expression618 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg; }
619
620 static const unsigned depth = left_type::depth + 1;
621 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
622 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
623 //
624 // Horrible workaround for gcc-4.6.x which always prefers the template
625 // operator bool() rather than the non-template operator when converting to
626 // an arithmetic type:
627 //
628 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression629 explicit operator T() const
630 {
631 result_type r(*this);
632 return static_cast<bool>(r);
633 }
634 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::expression635 explicit operator T() const
636 {
637 return static_cast<T>(static_cast<result_type>(*this));
638 }
639 #else
640 template <class T
641 #ifndef __SUNPRO_CC
642 ,
643 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
644 #endif
645 >
operator Tboost::multiprecision::detail::expression646 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
647 {
648 return static_cast<T>(static_cast<result_type>(*this));
649 }
operator boolboost::multiprecision::detail::expression650 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
651 {
652 result_type r(*this);
653 return static_cast<bool>(r);
654 }
655 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression656 BOOST_MP_FORCEINLINE explicit operator void() const
657 {}
658 #endif
659 #endif
660 #else
operator unmentionable_typeboost::multiprecision::detail::expression661 operator unmentionable_type() const
662 {
663 result_type r(*this);
664 return r ? &unmentionable::proc : 0;
665 }
666 #endif
667
668 template <class T>
convert_toboost::multiprecision::detail::expression669 BOOST_MP_CXX14_CONSTEXPR T convert_to()
670 {
671 result_type r(*this);
672 return r.template convert_to<T>();
673 }
674
675 private:
676 typename expression_storage<Arg1>::type arg;
677 expression& operator=(const expression&);
678 };
679
680 template <class Arg1>
681 struct expression<terminal, Arg1, void, void, void>
682 {
683 typedef mpl::int_<0> arity;
684 typedef Arg1 result_type;
685 typedef terminal tag_type;
686
expressionboost::multiprecision::detail::expression687 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
expressionboost::multiprecision::detail::expression688 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
689
690 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
691 //
692 // If we have static_assert we can give a more useful error message
693 // than if we simply have no operator defined at all:
694 //
695 template <class Other>
operator =boost::multiprecision::detail::expression696 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
697 {
698 // This should always fail:
699 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?");
700 return *this;
701 }
operator ++boost::multiprecision::detail::expression702 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
703 {
704 // This should always fail:
705 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?");
706 return *this;
707 }
operator ++boost::multiprecision::detail::expression708 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
709 {
710 // This should always fail:
711 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?");
712 return *this;
713 }
operator --boost::multiprecision::detail::expression714 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
715 {
716 // This should always fail:
717 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?");
718 return *this;
719 }
operator --boost::multiprecision::detail::expression720 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
721 {
722 // This should always fail:
723 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?");
724 return *this;
725 }
726 template <class Other>
operator +=boost::multiprecision::detail::expression727 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
728 {
729 // This should always fail:
730 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
731 return *this;
732 }
733 template <class Other>
operator -=boost::multiprecision::detail::expression734 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
735 {
736 // This should always fail:
737 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
738 return *this;
739 }
740 template <class Other>
operator *=boost::multiprecision::detail::expression741 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
742 {
743 // This should always fail:
744 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
745 return *this;
746 }
747 template <class Other>
operator /=boost::multiprecision::detail::expression748 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
749 {
750 // This should always fail:
751 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
752 return *this;
753 }
754 template <class Other>
operator %=boost::multiprecision::detail::expression755 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
756 {
757 // This should always fail:
758 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
759 return *this;
760 }
761 template <class Other>
operator |=boost::multiprecision::detail::expression762 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
763 {
764 // This should always fail:
765 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
766 return *this;
767 }
768 template <class Other>
operator &=boost::multiprecision::detail::expression769 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
770 {
771 // This should always fail:
772 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
773 return *this;
774 }
775 template <class Other>
operator ^=boost::multiprecision::detail::expression776 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
777 {
778 // This should always fail:
779 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
780 return *this;
781 }
782 template <class Other>
operator <<=boost::multiprecision::detail::expression783 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
784 {
785 // This should always fail:
786 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?");
787 return *this;
788 }
789 template <class Other>
operator >>=boost::multiprecision::detail::expression790 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
791 {
792 // This should always fail:
793 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?");
794 return *this;
795 }
796 #endif
797
valueboost::multiprecision::detail::expression798 BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const BOOST_NOEXCEPT
799 {
800 return arg;
801 }
802
803 static const unsigned depth = 0;
804
805 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
806 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
807 //
808 // Horrible workaround for gcc-4.6.x which always prefers the template
809 // operator bool() rather than the non-template operator when converting to
810 // an arithmetic type:
811 //
812 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression813 explicit operator T() const
814 {
815 result_type r(*this);
816 return static_cast<bool>(r);
817 }
818 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::expression819 explicit operator T() const
820 {
821 return static_cast<T>(static_cast<result_type>(*this));
822 }
823 #else
824 template <class T
825 #ifndef __SUNPRO_CC
826 ,
827 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
828 #endif
829 >
operator Tboost::multiprecision::detail::expression830 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
831 {
832 return static_cast<T>(static_cast<result_type>(*this));
833 }
operator boolboost::multiprecision::detail::expression834 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
835 {
836 result_type r(*this);
837 return static_cast<bool>(r);
838 }
839 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression840 BOOST_MP_FORCEINLINE explicit operator void() const
841 {}
842 #endif
843 #endif
844 #else
operator unmentionable_typeboost::multiprecision::detail::expression845 operator unmentionable_type() const
846 {
847 return arg ? &unmentionable::proc : 0;
848 }
849 #endif
850
851 template <class T>
convert_toboost::multiprecision::detail::expression852 BOOST_MP_CXX14_CONSTEXPR T convert_to()
853 {
854 result_type r(*this);
855 return r.template convert_to<T>();
856 }
857
858 private:
859 typename expression_storage<Arg1>::type arg;
860 expression& operator=(const expression&);
861 };
862
863 template <class tag, class Arg1, class Arg2>
864 struct expression<tag, Arg1, Arg2, void, void>
865 {
866 typedef mpl::int_<2> arity;
867 typedef typename arg_type<Arg1>::type left_type;
868 typedef typename arg_type<Arg2>::type right_type;
869 typedef typename left_type::result_type left_result_type;
870 typedef typename right_type::result_type right_result_type;
871 typedef typename combine_expression<left_result_type, right_result_type>::type result_type;
872 typedef tag tag_type;
873
expressionboost::multiprecision::detail::expression874 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
expressionboost::multiprecision::detail::expression875 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
876
877 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
878 //
879 // If we have static_assert we can give a more useful error message
880 // than if we simply have no operator defined at all:
881 //
882 template <class Other>
operator =boost::multiprecision::detail::expression883 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
884 {
885 // This should always fail:
886 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?");
887 return *this;
888 }
operator ++boost::multiprecision::detail::expression889 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
890 {
891 // This should always fail:
892 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?");
893 return *this;
894 }
operator ++boost::multiprecision::detail::expression895 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
896 {
897 // This should always fail:
898 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?");
899 return *this;
900 }
operator --boost::multiprecision::detail::expression901 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
902 {
903 // This should always fail:
904 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?");
905 return *this;
906 }
operator --boost::multiprecision::detail::expression907 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
908 {
909 // This should always fail:
910 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?");
911 return *this;
912 }
913 template <class Other>
operator +=boost::multiprecision::detail::expression914 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
915 {
916 // This should always fail:
917 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
918 return *this;
919 }
920 template <class Other>
operator -=boost::multiprecision::detail::expression921 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
922 {
923 // This should always fail:
924 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
925 return *this;
926 }
927 template <class Other>
operator *=boost::multiprecision::detail::expression928 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
929 {
930 // This should always fail:
931 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
932 return *this;
933 }
934 template <class Other>
operator /=boost::multiprecision::detail::expression935 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
936 {
937 // This should always fail:
938 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
939 return *this;
940 }
941 template <class Other>
operator %=boost::multiprecision::detail::expression942 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
943 {
944 // This should always fail:
945 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
946 return *this;
947 }
948 template <class Other>
operator |=boost::multiprecision::detail::expression949 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
950 {
951 // This should always fail:
952 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
953 return *this;
954 }
955 template <class Other>
operator &=boost::multiprecision::detail::expression956 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
957 {
958 // This should always fail:
959 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
960 return *this;
961 }
962 template <class Other>
operator ^=boost::multiprecision::detail::expression963 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
964 {
965 // This should always fail:
966 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
967 return *this;
968 }
969 template <class Other>
operator <<=boost::multiprecision::detail::expression970 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
971 {
972 // This should always fail:
973 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?");
974 return *this;
975 }
976 template <class Other>
operator >>=boost::multiprecision::detail::expression977 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
978 {
979 // This should always fail:
980 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?");
981 return *this;
982 }
983 #endif
984
leftboost::multiprecision::detail::expression985 BOOST_MP_CXX14_CONSTEXPR left_type left() const
986 {
987 return left_type(arg1);
988 }
rightboost::multiprecision::detail::expression989 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg2); }
left_refboost::multiprecision::detail::expression990 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
right_refboost::multiprecision::detail::expression991 BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const BOOST_NOEXCEPT { return arg2; }
992
993 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
994 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
995 //
996 // Horrible workaround for gcc-4.6.x which always prefers the template
997 // operator bool() rather than the non-template operator when converting to
998 // an arithmetic type:
999 //
1000 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1001 explicit operator T() const
1002 {
1003 result_type r(*this);
1004 return static_cast<bool>(r);
1005 }
1006 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::expression1007 explicit operator T() const
1008 {
1009 return static_cast<T>(static_cast<result_type>(*this));
1010 }
1011 #else
1012 template <class T
1013 #ifndef __SUNPRO_CC
1014 ,
1015 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
1016 #endif
1017 >
operator Tboost::multiprecision::detail::expression1018 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1019 {
1020 return static_cast<T>(static_cast<result_type>(*this));
1021 }
operator boolboost::multiprecision::detail::expression1022 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1023 {
1024 result_type r(*this);
1025 return static_cast<bool>(r);
1026 }
1027 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1028 BOOST_MP_FORCEINLINE explicit operator void() const
1029 {}
1030 #endif
1031 #endif
1032 #else
operator unmentionable_typeboost::multiprecision::detail::expression1033 operator unmentionable_type() const
1034 {
1035 result_type r(*this);
1036 return r ? &unmentionable::proc : 0;
1037 }
1038 #endif
1039 template <class T>
convert_toboost::multiprecision::detail::expression1040 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1041 {
1042 result_type r(*this);
1043 return r.template convert_to<T>();
1044 }
1045
1046 static const BOOST_MP_CXX14_CONSTEXPR unsigned left_depth = left_type::depth + 1;
1047 static const BOOST_MP_CXX14_CONSTEXPR unsigned right_depth = right_type::depth + 1;
1048 static const BOOST_MP_CXX14_CONSTEXPR unsigned depth = left_depth > right_depth ? left_depth : right_depth;
1049
1050 private:
1051 typename expression_storage<Arg1>::type arg1;
1052 typename expression_storage<Arg2>::type arg2;
1053 expression& operator=(const expression&);
1054 };
1055
1056 template <class tag, class Arg1, class Arg2, class Arg3>
1057 struct expression<tag, Arg1, Arg2, Arg3, void>
1058 {
1059 typedef mpl::int_<3> arity;
1060 typedef typename arg_type<Arg1>::type left_type;
1061 typedef typename arg_type<Arg2>::type middle_type;
1062 typedef typename arg_type<Arg3>::type right_type;
1063 typedef typename left_type::result_type left_result_type;
1064 typedef typename middle_type::result_type middle_result_type;
1065 typedef typename right_type::result_type right_result_type;
1066 typedef typename combine_expression<
1067 left_result_type,
1068 typename combine_expression<right_result_type, middle_result_type>::type>::type result_type;
1069 typedef tag tag_type;
1070
expressionboost::multiprecision::detail::expression1071 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
expressionboost::multiprecision::detail::expression1072 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
1073
1074 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1075 //
1076 // If we have static_assert we can give a more useful error message
1077 // than if we simply have no operator defined at all:
1078 //
1079 template <class Other>
operator =boost::multiprecision::detail::expression1080 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1081 {
1082 // This should always fail:
1083 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?");
1084 return *this;
1085 }
operator ++boost::multiprecision::detail::expression1086 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1087 {
1088 // This should always fail:
1089 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?");
1090 return *this;
1091 }
operator ++boost::multiprecision::detail::expression1092 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1093 {
1094 // This should always fail:
1095 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?");
1096 return *this;
1097 }
operator --boost::multiprecision::detail::expression1098 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1099 {
1100 // This should always fail:
1101 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?");
1102 return *this;
1103 }
operator --boost::multiprecision::detail::expression1104 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1105 {
1106 // This should always fail:
1107 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?");
1108 return *this;
1109 }
1110 template <class Other>
operator +=boost::multiprecision::detail::expression1111 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1112 {
1113 // This should always fail:
1114 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1115 return *this;
1116 }
1117 template <class Other>
operator -=boost::multiprecision::detail::expression1118 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1119 {
1120 // This should always fail:
1121 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1122 return *this;
1123 }
1124 template <class Other>
operator *=boost::multiprecision::detail::expression1125 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1126 {
1127 // This should always fail:
1128 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1129 return *this;
1130 }
1131 template <class Other>
operator /=boost::multiprecision::detail::expression1132 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1133 {
1134 // This should always fail:
1135 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1136 return *this;
1137 }
1138 template <class Other>
operator %=boost::multiprecision::detail::expression1139 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1140 {
1141 // This should always fail:
1142 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1143 return *this;
1144 }
1145 template <class Other>
operator |=boost::multiprecision::detail::expression1146 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1147 {
1148 // This should always fail:
1149 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1150 return *this;
1151 }
1152 template <class Other>
operator &=boost::multiprecision::detail::expression1153 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1154 {
1155 // This should always fail:
1156 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1157 return *this;
1158 }
1159 template <class Other>
operator ^=boost::multiprecision::detail::expression1160 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1161 {
1162 // This should always fail:
1163 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1164 return *this;
1165 }
1166 template <class Other>
operator <<=boost::multiprecision::detail::expression1167 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1168 {
1169 // This should always fail:
1170 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?");
1171 return *this;
1172 }
1173 template <class Other>
operator >>=boost::multiprecision::detail::expression1174 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1175 {
1176 // This should always fail:
1177 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?");
1178 return *this;
1179 }
1180 #endif
1181
leftboost::multiprecision::detail::expression1182 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1183 {
1184 return left_type(arg1);
1185 }
middleboost::multiprecision::detail::expression1186 BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
rightboost::multiprecision::detail::expression1187 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg3); }
left_refboost::multiprecision::detail::expression1188 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
middle_refboost::multiprecision::detail::expression1189 BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const BOOST_NOEXCEPT { return arg2; }
right_refboost::multiprecision::detail::expression1190 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const BOOST_NOEXCEPT { return arg3; }
1191
1192 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1193 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1194 //
1195 // Horrible workaround for gcc-4.6.x which always prefers the template
1196 // operator bool() rather than the non-template operator when converting to
1197 // an arithmetic type:
1198 //
1199 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1200 explicit operator T() const
1201 {
1202 result_type r(*this);
1203 return static_cast<bool>(r);
1204 }
1205 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::expression1206 explicit operator T() const
1207 {
1208 return static_cast<T>(static_cast<result_type>(*this));
1209 }
1210 #else
1211 template <class T
1212 #ifndef __SUNPRO_CC
1213 ,
1214 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
1215 #endif
1216 >
operator Tboost::multiprecision::detail::expression1217 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1218 {
1219 return static_cast<T>(static_cast<result_type>(*this));
1220 }
operator boolboost::multiprecision::detail::expression1221 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1222 {
1223 result_type r(*this);
1224 return static_cast<bool>(r);
1225 }
1226 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1227 BOOST_MP_FORCEINLINE explicit operator void() const
1228 {}
1229 #endif
1230 #endif
1231 #else
operator unmentionable_typeboost::multiprecision::detail::expression1232 operator unmentionable_type() const
1233 {
1234 result_type r(*this);
1235 return r ? &unmentionable::proc : 0;
1236 }
1237 #endif
1238 template <class T>
convert_toboost::multiprecision::detail::expression1239 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1240 {
1241 result_type r(*this);
1242 return r.template convert_to<T>();
1243 }
1244
1245 static const unsigned left_depth = left_type::depth + 1;
1246 static const unsigned middle_depth = middle_type::depth + 1;
1247 static const unsigned right_depth = right_type::depth + 1;
1248 static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
1249
1250 private:
1251 typename expression_storage<Arg1>::type arg1;
1252 typename expression_storage<Arg2>::type arg2;
1253 typename expression_storage<Arg3>::type arg3;
1254 expression& operator=(const expression&);
1255 };
1256
1257 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1258 struct expression
1259 {
1260 typedef mpl::int_<4> arity;
1261 typedef typename arg_type<Arg1>::type left_type;
1262 typedef typename arg_type<Arg2>::type left_middle_type;
1263 typedef typename arg_type<Arg3>::type right_middle_type;
1264 typedef typename arg_type<Arg4>::type right_type;
1265 typedef typename left_type::result_type left_result_type;
1266 typedef typename left_middle_type::result_type left_middle_result_type;
1267 typedef typename right_middle_type::result_type right_middle_result_type;
1268 typedef typename right_type::result_type right_result_type;
1269 typedef typename combine_expression<
1270 left_result_type,
1271 typename combine_expression<
1272 left_middle_result_type,
1273 typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type result_type;
1274 typedef tag tag_type;
1275
expressionboost::multiprecision::detail::expression1276 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::expression1277 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
1278
1279 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1280 //
1281 // If we have static_assert we can give a more useful error message
1282 // than if we simply have no operator defined at all:
1283 //
1284 template <class Other>
operator =boost::multiprecision::detail::expression1285 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1286 {
1287 // This should always fail:
1288 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?");
1289 return *this;
1290 }
operator ++boost::multiprecision::detail::expression1291 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1292 {
1293 // This should always fail:
1294 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?");
1295 return *this;
1296 }
operator ++boost::multiprecision::detail::expression1297 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1298 {
1299 // This should always fail:
1300 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?");
1301 return *this;
1302 }
operator --boost::multiprecision::detail::expression1303 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1304 {
1305 // This should always fail:
1306 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?");
1307 return *this;
1308 }
operator --boost::multiprecision::detail::expression1309 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1310 {
1311 // This should always fail:
1312 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?");
1313 return *this;
1314 }
1315 template <class Other>
operator +=boost::multiprecision::detail::expression1316 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1317 {
1318 // This should always fail:
1319 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1320 return *this;
1321 }
1322 template <class Other>
operator -=boost::multiprecision::detail::expression1323 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1324 {
1325 // This should always fail:
1326 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1327 return *this;
1328 }
1329 template <class Other>
operator *=boost::multiprecision::detail::expression1330 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1331 {
1332 // This should always fail:
1333 static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1334 return *this;
1335 }
1336 template <class Other>
operator /=boost::multiprecision::detail::expression1337 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1338 {
1339 // This should always fail:
1340 static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1341 return *this;
1342 }
1343 template <class Other>
operator %=boost::multiprecision::detail::expression1344 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1345 {
1346 // This should always fail:
1347 static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1348 return *this;
1349 }
1350 template <class Other>
operator |=boost::multiprecision::detail::expression1351 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1352 {
1353 // This should always fail:
1354 static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1355 return *this;
1356 }
1357 template <class Other>
operator &=boost::multiprecision::detail::expression1358 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1359 {
1360 // This should always fail:
1361 static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1362 return *this;
1363 }
1364 template <class Other>
operator ^=boost::multiprecision::detail::expression1365 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1366 {
1367 // This should always fail:
1368 static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1369 return *this;
1370 }
1371 template <class Other>
operator <<=boost::multiprecision::detail::expression1372 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1373 {
1374 // This should always fail:
1375 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?");
1376 return *this;
1377 }
1378 template <class Other>
operator >>=boost::multiprecision::detail::expression1379 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1380 {
1381 // This should always fail:
1382 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?");
1383 return *this;
1384 }
1385 #endif
1386
leftboost::multiprecision::detail::expression1387 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1388 {
1389 return left_type(arg1);
1390 }
left_middleboost::multiprecision::detail::expression1391 BOOST_MP_CXX14_CONSTEXPR left_middle_type left_middle() const { return left_middle_type(arg2); }
right_middleboost::multiprecision::detail::expression1392 BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
rightboost::multiprecision::detail::expression1393 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg4); }
left_refboost::multiprecision::detail::expression1394 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
left_middle_refboost::multiprecision::detail::expression1395 BOOST_MP_CXX14_CONSTEXPR const Arg2& left_middle_ref() const BOOST_NOEXCEPT { return arg2; }
right_middle_refboost::multiprecision::detail::expression1396 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_middle_ref() const BOOST_NOEXCEPT { return arg3; }
right_refboost::multiprecision::detail::expression1397 BOOST_MP_CXX14_CONSTEXPR const Arg4& right_ref() const BOOST_NOEXCEPT { return arg4; }
1398
1399 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1400 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1401 //
1402 // Horrible workaround for gcc-4.6.x which always prefers the template
1403 // operator bool() rather than the non-template operator when converting to
1404 // an arithmetic type:
1405 //
1406 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1407 explicit operator T() const
1408 {
1409 result_type r(*this);
1410 return static_cast<bool>(r);
1411 }
1412 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::expression1413 explicit operator T() const
1414 {
1415 return static_cast<T>(static_cast<result_type>(*this));
1416 }
1417 #else
1418 template <class T
1419 #ifndef __SUNPRO_CC
1420 ,
1421 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
1422 #endif
1423 >
operator Tboost::multiprecision::detail::expression1424 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1425 {
1426 return static_cast<T>(static_cast<result_type>(*this));
1427 }
operator boolboost::multiprecision::detail::expression1428 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1429 {
1430 result_type r(*this);
1431 return static_cast<bool>(r);
1432 }
1433 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1434 BOOST_MP_FORCEINLINE explicit operator void() const
1435 {}
1436 #endif
1437 #endif
1438 #else
operator unmentionable_typeboost::multiprecision::detail::expression1439 operator unmentionable_type() const
1440 {
1441 result_type r(*this);
1442 return r ? &unmentionable::proc : 0;
1443 }
1444 #endif
1445 template <class T>
convert_toboost::multiprecision::detail::expression1446 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1447 {
1448 result_type r(*this);
1449 return r.template convert_to<T>();
1450 }
1451
1452 static const unsigned left_depth = left_type::depth + 1;
1453 static const unsigned left_middle_depth = left_middle_type::depth + 1;
1454 static const unsigned right_middle_depth = right_middle_type::depth + 1;
1455 static const unsigned right_depth = right_type::depth + 1;
1456
1457 static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
1458 static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
1459
1460 static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
1461
1462 private:
1463 typename expression_storage<Arg1>::type arg1;
1464 typename expression_storage<Arg2>::type arg2;
1465 typename expression_storage<Arg3>::type arg3;
1466 typename expression_storage<Arg4>::type arg4;
1467 expression& operator=(const expression&);
1468 };
1469
1470 template <class T>
1471 struct digits2
1472 {
1473 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
1474 BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
1475 // If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
1476 BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
1477 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::digits21478 static inline BOOST_CONSTEXPR long value() BOOST_NOEXCEPT { return m_value; }
1479 };
1480
1481 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
1482 #ifdef _MSC_VER
1483 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1484 #else
1485 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1486 #endif
1487 #endif
1488
1489 template <class S>
format_float_string(S & str,boost::intmax_t my_exp,boost::intmax_t digits,std::ios_base::fmtflags f,bool iszero)1490 void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
1491 {
1492 typedef typename S::size_type size_type;
1493 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
1494 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
1495 bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
1496 bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
1497
1498 bool neg = str.size() && (str[0] == '-');
1499
1500 if (neg)
1501 str.erase(0, 1);
1502
1503 if (digits == 0)
1504 {
1505 digits = (std::max)(str.size(), size_type(16));
1506 }
1507
1508 if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
1509 {
1510 // We will be printing zero, even though the value might not
1511 // actually be zero (it just may have been rounded to zero).
1512 str = "0";
1513 if (scientific || fixed)
1514 {
1515 str.append(1, '.');
1516 str.append(size_type(digits), '0');
1517 if (scientific)
1518 str.append("e+00");
1519 }
1520 else
1521 {
1522 if (showpoint)
1523 {
1524 str.append(1, '.');
1525 if (digits > 1)
1526 str.append(size_type(digits - 1), '0');
1527 }
1528 }
1529 if (neg)
1530 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1531 else if (showpos)
1532 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1533 return;
1534 }
1535
1536 if (!fixed && !scientific && !showpoint)
1537 {
1538 //
1539 // Suppress trailing zeros:
1540 //
1541 std::string::iterator pos = str.end();
1542 while (pos != str.begin() && *--pos == '0')
1543 {
1544 }
1545 if (pos != str.end())
1546 ++pos;
1547 str.erase(pos, str.end());
1548 if (str.empty())
1549 str = '0';
1550 }
1551 else if (!fixed || (my_exp >= 0))
1552 {
1553 //
1554 // Pad out the end with zero's if we need to:
1555 //
1556 boost::intmax_t chars = str.size();
1557 chars = digits - chars;
1558 if (scientific)
1559 ++chars;
1560 if (chars > 0)
1561 {
1562 str.append(static_cast<std::string::size_type>(chars), '0');
1563 }
1564 }
1565
1566 if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
1567 {
1568 if (1 + my_exp > static_cast<boost::intmax_t>(str.size()))
1569 {
1570 // Just pad out the end with zeros:
1571 str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
1572 if (showpoint || fixed)
1573 str.append(".");
1574 }
1575 else if (my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
1576 {
1577 if (my_exp < 0)
1578 {
1579 str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
1580 str.insert(static_cast<std::string::size_type>(0), "0.");
1581 }
1582 else
1583 {
1584 // Insert the decimal point:
1585 str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
1586 }
1587 }
1588 else if (showpoint || fixed) // we have exactly the digits we require to left of the point
1589 str += ".";
1590
1591 if (fixed)
1592 {
1593 // We may need to add trailing zeros:
1594 boost::intmax_t l = str.find('.') + 1;
1595 l = digits - (str.size() - l);
1596 if (l > 0)
1597 str.append(size_type(l), '0');
1598 }
1599 }
1600 else
1601 {
1602 BOOST_MP_USING_ABS
1603 // Scientific format:
1604 if (showpoint || (str.size() > 1))
1605 str.insert(static_cast<std::string::size_type>(1u), 1, '.');
1606 str.append(static_cast<std::string::size_type>(1u), 'e');
1607 S e = boost::lexical_cast<S>(abs(my_exp));
1608 if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
1609 e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
1610 if (my_exp < 0)
1611 e.insert(static_cast<std::string::size_type>(0), 1, '-');
1612 else
1613 e.insert(static_cast<std::string::size_type>(0), 1, '+');
1614 str.append(e);
1615 }
1616 if (neg)
1617 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1618 else if (showpos)
1619 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1620 }
1621
1622 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::true_ &)1623 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
1624 {
1625 if (val > (std::numeric_limits<std::size_t>::max)())
1626 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1627 if (val < 0)
1628 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1629 }
1630 template <class V>
check_shift_range(V val,const mpl::false_ &,const mpl::true_ &)1631 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
1632 {
1633 if (val < 0)
1634 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1635 }
1636 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::false_ &)1637 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
1638 {
1639 if (val > (std::numeric_limits<std::size_t>::max)())
1640 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1641 }
1642 template <class V>
check_shift_range(V,const mpl::false_ &,const mpl::false_ &)1643 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT {}
1644
1645 template <class T>
evaluate_if_expression(const T & val)1646 BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
1647 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
evaluate_if_expression(const expression<tag,Arg1,Arg2,Arg3,Arg4> & val)1648 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; }
1649
1650 } // namespace detail
1651
1652 //
1653 // Traits class, lets us know what kind of number we have, defaults to a floating point type:
1654 //
1655 enum number_category_type
1656 {
1657 number_kind_unknown = -1,
1658 number_kind_integer = 0,
1659 number_kind_floating_point = 1,
1660 number_kind_rational = 2,
1661 number_kind_fixed_point = 3,
1662 number_kind_complex = 4
1663 };
1664
1665 template <class Num, bool, bool>
1666 struct number_category_base : public mpl::int_<number_kind_unknown>
1667 {};
1668 template <class Num>
1669 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)>
1670 {};
1671 template <class Num>
1672 struct number_category : public number_category_base<Num, boost::is_class<Num>::value || boost::is_arithmetic<Num>::value, boost::is_abstract<Num>::value>
1673 {};
1674 template <class Backend, expression_template_option ExpressionTemplates>
1675 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
1676 {};
1677 template <class tag, class A1, class A2, class A3, class A4>
1678 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1679 {};
1680 //
1681 // Specializations for types which do not always have numberic_limits specializations:
1682 //
1683 #ifdef BOOST_HAS_INT128
1684 template <>
1685 struct number_category<boost::int128_type> : public mpl::int_<number_kind_integer>
1686 {};
1687 template <>
1688 struct number_category<boost::uint128_type> : public mpl::int_<number_kind_integer>
1689 {};
1690 #endif
1691 #ifdef BOOST_HAS_FLOAT128
1692 template <>
1693 struct number_category<__float128> : public mpl::int_<number_kind_floating_point>
1694 {};
1695 #endif
1696
1697 template <class T>
1698 struct component_type
1699 {
1700 typedef T type;
1701 };
1702 template <class tag, class A1, class A2, class A3, class A4>
1703 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1704 {};
1705
1706 template <class T>
1707 struct scalar_result_from_possible_complex
1708 {
1709 typedef typename mpl::if_c<number_category<T>::value == number_kind_complex,
1710 typename component_type<T>::type, T>::type type;
1711 };
1712
1713 template <class T>
1714 struct complex_result_from_scalar; // individual backends must specialize this trait.
1715
1716 template <class T>
1717 struct is_unsigned_number : public mpl::false_
1718 {};
1719 template <class Backend, expression_template_option ExpressionTemplates>
1720 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
1721 {};
1722 template <class T>
1723 struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value>
1724 {};
1725 template <class T>
1726 struct is_interval_number : public mpl::false_
1727 {};
1728 template <class Backend, expression_template_option ExpressionTemplates>
1729 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
1730 {};
1731
1732 } // namespace multiprecision
1733 } // namespace boost
1734
1735 namespace boost { namespace math {
1736 namespace tools {
1737
1738 template <class T>
1739 struct promote_arg;
1740
1741 template <class tag, class A1, class A2, class A3, class A4>
1742 struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
1743 {
1744 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
1745 };
1746
1747 template <class R, class B, boost::multiprecision::expression_template_option ET>
real_cast(const boost::multiprecision::number<B,ET> & val)1748 inline R real_cast(const boost::multiprecision::number<B, ET>& val)
1749 {
1750 return val.template convert_to<R>();
1751 }
1752
1753 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)1754 inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
1755 {
1756 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
1757 return val_type(val).template convert_to<R>();
1758 }
1759
1760 template <class B, boost::multiprecision::expression_template_option ET>
1761 struct is_complex_type<boost::multiprecision::number<B, ET> > : public boost::mpl::bool_<boost::multiprecision::number_category<B>::value == boost::multiprecision::number_kind_complex> {};
1762
1763 } // namespace tools
1764
1765 namespace constants {
1766
1767 template <class T>
1768 struct is_explicitly_convertible_from_string;
1769
1770 template <class B, boost::multiprecision::expression_template_option ET>
1771 struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
1772 {
1773 static const bool value = true;
1774 };
1775
1776 } // namespace constants
1777
1778 }} // namespace boost::math
1779
1780 #ifdef BOOST_MSVC
1781 #pragma warning(pop)
1782 #endif
1783
1784 #endif // BOOST_MATH_BIG_NUM_BASE_HPP
1785