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 #ifdef __has_include
53 # if __has_include(<version>)
54 # include <version>
55 # ifdef __cpp_lib_is_constant_evaluated
56 # include <type_traits>
57 # define BOOST_MP_HAS_IS_CONSTANT_EVALUATED
58 # endif
59 # endif
60 #endif
61
62 #ifdef __has_builtin
63 #if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
64 #define BOOST_MP_CLANG_CD
65 #endif
66 #endif
67
68 #if defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
69 # define BOOST_MP_IS_CONST_EVALUATED(x) std::is_constant_evaluated()
70 #elif (defined(BOOST_GCC) && !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9)) || defined(BOOST_MP_CLANG_CD)
71 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_is_constant_evaluated()
72 #elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_GCC) && (__GNUC__ >= 6)
73 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_constant_p(x)
74 #else
75 # define BOOST_MP_NO_CONSTEXPR_DETECTION
76 #endif
77
78 #define BOOST_MP_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
79 //
80 // Early compiler versions trip over the constexpr code:
81 //
82 #if defined(__clang__) && (__clang_major__ < 5)
83 #undef BOOST_MP_CXX14_CONSTEXPR
84 #define BOOST_MP_CXX14_CONSTEXPR
85 #endif
86 #if defined(__apple_build_version__) && (__clang_major__ < 9)
87 #undef BOOST_MP_CXX14_CONSTEXPR
88 #define BOOST_MP_CXX14_CONSTEXPR
89 #endif
90 #if defined(BOOST_GCC) && (__GNUC__ < 6)
91 #undef BOOST_MP_CXX14_CONSTEXPR
92 #define BOOST_MP_CXX14_CONSTEXPR
93 #endif
94
95 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
96 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION
97 #else
98 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION constexpr
99 #endif
100
101 #ifdef BOOST_MSVC
102 #pragma warning(push)
103 #pragma warning(disable : 6326)
104 #endif
105
106 namespace boost {
107 namespace multiprecision {
108
109 enum expression_template_option
110 {
111 et_off = 0,
112 et_on = 1
113 };
114
115 template <class Backend>
116 struct expression_template_default
117 {
118 static const expression_template_option value = et_on;
119 };
120
121 template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
122 class number;
123
124 template <class T>
125 struct is_number : public mpl::false_
126 {};
127
128 template <class Backend, expression_template_option ExpressionTemplates>
129 struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_
130 {};
131
132 template <class T>
133 struct is_et_number : public mpl::false_
134 {};
135
136 template <class Backend>
137 struct is_et_number<number<Backend, et_on> > : public mpl::true_
138 {};
139
140 template <class T>
141 struct is_no_et_number : public mpl::false_
142 {};
143
144 template <class Backend>
145 struct is_no_et_number<number<Backend, et_off> > : public mpl::true_
146 {};
147
148 namespace detail {
149
150 // Forward-declare an expression wrapper
151 template <class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
152 struct expression;
153
154 } // namespace detail
155
156 template <class T>
157 struct is_number_expression : public mpl::false_
158 {};
159
160 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
161 struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_
162 {};
163
164 template <class T, class Num>
165 struct is_compatible_arithmetic_type
166 : public mpl::bool_<
167 is_convertible<T, Num>::value && !is_same<T, Num>::value && !is_number_expression<T>::value>
168 {};
169
170 namespace detail {
171 //
172 // Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
173 //
174 template <class T>
abs(T t)175 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
176 {
177 // This strange expression avoids a hardware trap in the corner case
178 // that val is the most negative value permitted in boost::long_long_type.
179 // See https://svn.boost.org/trac/boost/ticket/9740.
180 return t < 0 ? T(1u) + T(-(t + 1)) : t;
181 }
182 template <class T>
abs(T t)183 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
184 {
185 return t;
186 }
187
188 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
189
190 template <class T>
unsigned_abs(T t)191 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), typename make_unsigned<T>::type>::type unsigned_abs(T t) BOOST_NOEXCEPT
192 {
193 // This strange expression avoids a hardware trap in the corner case
194 // that val is the most negative value permitted in boost::long_long_type.
195 // See https://svn.boost.org/trac/boost/ticket/9740.
196 return t < 0 ? static_cast<typename make_unsigned<T>::type>(1u) + static_cast<typename make_unsigned<T>::type>(-(t + 1)) : static_cast<typename make_unsigned<T>::type>(t);
197 }
198 template <class T>
unsigned_abs(T t)199 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
200 {
201 return t;
202 }
203
204 //
205 // Move support:
206 //
207 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
208 #define BOOST_MP_MOVE(x) std::move(x)
209 #else
210 #define BOOST_MP_MOVE(x) x
211 #endif
212
213 template <class T>
214 struct bits_of
215 {
216 BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
217 static const unsigned value =
218 std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
219 : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
220 };
221
222 #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
223 template <>
224 struct bits_of<__float128>
225 {
226 static const unsigned value = 113;
227 };
228 #endif
229
230 template <int b>
231 struct has_enough_bits
232 {
233 template <class T>
234 struct type : public mpl::bool_<bits_of<T>::value >= b>
235 {};
236 };
237
238 template <class Val, class Backend, class Tag>
239 struct canonical_imp
240 {
241 typedef typename remove_cv<typename decay<const Val>::type>::type type;
242 };
243 template <class B, class Backend, class Tag>
244 struct canonical_imp<number<B, et_on>, Backend, Tag>
245 {
246 typedef B type;
247 };
248 template <class B, class Backend, class Tag>
249 struct canonical_imp<number<B, et_off>, Backend, Tag>
250 {
251 typedef B type;
252 };
253 #ifdef __SUNPRO_CC
254 template <class B, class Backend>
255 struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
256 {
257 typedef B type;
258 };
259 template <class B, class Backend>
260 struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
261 {
262 typedef B type;
263 };
264 #endif
265 template <class Val, class Backend>
266 struct canonical_imp<Val, Backend, mpl::int_<0> >
267 {
268 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
269 typedef typename mpl::find_if<
270 typename Backend::signed_types,
271 pred_type>::type iter_type;
272 typedef typename mpl::end<typename Backend::signed_types>::type end_type;
273 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
274 };
275 template <class Val, class Backend>
276 struct canonical_imp<Val, Backend, mpl::int_<1> >
277 {
278 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
279 typedef typename mpl::find_if<
280 typename Backend::unsigned_types,
281 pred_type>::type iter_type;
282 typedef typename mpl::end<typename Backend::unsigned_types>::type end_type;
283 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
284 };
285 template <class Val, class Backend>
286 struct canonical_imp<Val, Backend, mpl::int_<2> >
287 {
288 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
289 typedef typename mpl::find_if<
290 typename Backend::float_types,
291 pred_type>::type iter_type;
292 typedef typename mpl::end<typename Backend::float_types>::type end_type;
293 typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
294 };
295 template <class Val, class Backend>
296 struct canonical_imp<Val, Backend, mpl::int_<3> >
297 {
298 typedef const char* type;
299 };
300
301 template <class Val, class Backend>
302 struct canonical
303 {
304 typedef typename mpl::if_<
305 is_signed<Val>,
306 mpl::int_<0>,
307 typename mpl::if_<
308 is_unsigned<Val>,
309 mpl::int_<1>,
310 typename mpl::if_<
311 is_floating_point<Val>,
312 mpl::int_<2>,
313 typename mpl::if_<
314 mpl::or_<
315 is_convertible<Val, const char*>,
316 is_same<Val, std::string> >,
317 mpl::int_<3>,
318 mpl::int_<4> >::type>::type>::type>::type tag_type;
319
320 typedef typename canonical_imp<Val, Backend, tag_type>::type type;
321 };
322
323 struct terminal
324 {};
325 struct negate
326 {};
327 struct plus
328 {};
329 struct minus
330 {};
331 struct multiplies
332 {};
333 struct divides
334 {};
335 struct modulus
336 {};
337 struct shift_left
338 {};
339 struct shift_right
340 {};
341 struct bitwise_and
342 {};
343 struct bitwise_or
344 {};
345 struct bitwise_xor
346 {};
347 struct bitwise_complement
348 {};
349 struct add_immediates
350 {};
351 struct subtract_immediates
352 {};
353 struct multiply_immediates
354 {};
355 struct divide_immediates
356 {};
357 struct modulus_immediates
358 {};
359 struct bitwise_and_immediates
360 {};
361 struct bitwise_or_immediates
362 {};
363 struct bitwise_xor_immediates
364 {};
365 struct complement_immediates
366 {};
367 struct function
368 {};
369 struct multiply_add
370 {};
371 struct multiply_subtract
372 {};
373
374 template <class T>
375 struct backend_type;
376
377 template <class T, expression_template_option ExpressionTemplates>
378 struct backend_type<number<T, ExpressionTemplates> >
379 {
380 typedef T type;
381 };
382
383 template <class tag, class A1, class A2, class A3, class A4>
384 struct backend_type<expression<tag, A1, A2, A3, A4> >
385 {
386 typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
387 };
388
389 template <class T1, class T2>
390 struct combine_expression
391 {
392 #ifdef BOOST_NO_CXX11_DECLTYPE
393 typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
394 #else
395 typedef decltype(T1() + T2()) type;
396 #endif
397 };
398
399 template <class T1, expression_template_option ExpressionTemplates, class T2>
400 struct combine_expression<number<T1, ExpressionTemplates>, T2>
401 {
402 typedef number<T1, ExpressionTemplates> type;
403 };
404
405 template <class T1, class T2, expression_template_option ExpressionTemplates>
406 struct combine_expression<T1, number<T2, ExpressionTemplates> >
407 {
408 typedef number<T2, ExpressionTemplates> type;
409 };
410
411 template <class T, expression_template_option ExpressionTemplates>
412 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
413 {
414 typedef number<T, ExpressionTemplates> type;
415 };
416
417 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
418 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
419 {
420 typedef typename mpl::if_c<
421 is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
422 number<T1, ExpressionTemplates1>,
423 number<T2, ExpressionTemplates2> >::type type;
424 };
425
426 template <class T>
427 struct arg_type
428 {
429 typedef expression<terminal, T> type;
430 };
431
432 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
433 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
434 {
435 typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
436 };
437
438 struct unmentionable
439 {
procboost::multiprecision::detail::unmentionable440 unmentionable* proc() { return 0; }
441 };
442
443 typedef unmentionable* (unmentionable::*unmentionable_type)();
444
445 template <class T, bool b>
446 struct expression_storage_base
447 {
448 typedef const T& type;
449 };
450
451 template <class T>
452 struct expression_storage_base<T, true>
453 {
454 typedef T type;
455 };
456
457 template <class T>
458 struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value>
459 {};
460
461 template <class T>
462 struct expression_storage<T*>
463 {
464 typedef T* type;
465 };
466
467 template <class T>
468 struct expression_storage<const T*>
469 {
470 typedef const T* type;
471 };
472
473 template <class tag, class A1, class A2, class A3, class A4>
474 struct expression_storage<expression<tag, A1, A2, A3, A4> >
475 {
476 typedef expression<tag, A1, A2, A3, A4> type;
477 };
478
479 template <class tag, class Arg1>
480 struct expression<tag, Arg1, void, void, void>
481 {
482 typedef mpl::int_<1> arity;
483 typedef typename arg_type<Arg1>::type left_type;
484 typedef typename left_type::result_type left_result_type;
485 typedef typename left_type::result_type result_type;
486 typedef tag tag_type;
487
expressionboost::multiprecision::detail::expression488 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
expressionboost::multiprecision::detail::expression489 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
490
491 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
492 //
493 // If we have static_assert we can give a more useful error message
494 // than if we simply have no operator defined at all:
495 //
496 template <class Other>
operator =boost::multiprecision::detail::expression497 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
498 {
499 // This should always fail:
500 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
501 return *this;
502 }
operator ++boost::multiprecision::detail::expression503 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
504 {
505 // This should always fail:
506 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
507 return *this;
508 }
operator ++boost::multiprecision::detail::expression509 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
510 {
511 // This should always fail:
512 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
513 return *this;
514 }
operator --boost::multiprecision::detail::expression515 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
516 {
517 // This should always fail:
518 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
519 return *this;
520 }
operator --boost::multiprecision::detail::expression521 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
522 {
523 // This should always fail:
524 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
525 return *this;
526 }
527 template <class Other>
operator +=boost::multiprecision::detail::expression528 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
529 {
530 // This should always fail:
531 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
532 return *this;
533 }
534 template <class Other>
operator -=boost::multiprecision::detail::expression535 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
536 {
537 // This should always fail:
538 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
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 #endif
598
leftboost::multiprecision::detail::expression599 BOOST_MP_CXX14_CONSTEXPR left_type left() const
600 {
601 return left_type(arg);
602 }
603
left_refboost::multiprecision::detail::expression604 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg; }
605
606 static const unsigned depth = left_type::depth + 1;
607 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
608 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
609 //
610 // Horrible workaround for gcc-4.6.x which always prefers the template
611 // operator bool() rather than the non-template operator when converting to
612 // an arithmetic type:
613 //
614 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression615 explicit operator T() const
616 {
617 result_type r(*this);
618 return static_cast<bool>(r);
619 }
620 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression621 explicit operator T() const
622 {
623 return static_cast<T>(static_cast<result_type>(*this));
624 }
625 #else
626 template <class T
627 #ifndef __SUNPRO_CC
628 ,
629 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
630 #endif
631 >
operator Tboost::multiprecision::detail::expression632 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
633 {
634 return static_cast<T>(static_cast<result_type>(*this));
635 }
operator boolboost::multiprecision::detail::expression636 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
637 {
638 result_type r(*this);
639 return static_cast<bool>(r);
640 }
641 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression642 BOOST_MP_FORCEINLINE explicit operator void() const
643 {}
644 #endif
645 #endif
646 #else
operator unmentionable_typeboost::multiprecision::detail::expression647 operator unmentionable_type() const
648 {
649 result_type r(*this);
650 return r ? &unmentionable::proc : 0;
651 }
652 #endif
653
654 template <class T>
convert_toboost::multiprecision::detail::expression655 BOOST_MP_CXX14_CONSTEXPR T convert_to()
656 {
657 result_type r(*this);
658 return r.template convert_to<T>();
659 }
660
661 private:
662 typename expression_storage<Arg1>::type arg;
663 expression& operator=(const expression&);
664 };
665
666 template <class Arg1>
667 struct expression<terminal, Arg1, void, void, void>
668 {
669 typedef mpl::int_<0> arity;
670 typedef Arg1 result_type;
671 typedef terminal tag_type;
672
expressionboost::multiprecision::detail::expression673 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
expressionboost::multiprecision::detail::expression674 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
675
676 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
677 //
678 // If we have static_assert we can give a more useful error message
679 // than if we simply have no operator defined at all:
680 //
681 template <class Other>
operator =boost::multiprecision::detail::expression682 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
683 {
684 // This should always fail:
685 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
686 return *this;
687 }
operator ++boost::multiprecision::detail::expression688 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
689 {
690 // This should always fail:
691 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
692 return *this;
693 }
operator ++boost::multiprecision::detail::expression694 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
695 {
696 // This should always fail:
697 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
698 return *this;
699 }
operator --boost::multiprecision::detail::expression700 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
701 {
702 // This should always fail:
703 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
704 return *this;
705 }
operator --boost::multiprecision::detail::expression706 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
707 {
708 // This should always fail:
709 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
710 return *this;
711 }
712 template <class Other>
operator +=boost::multiprecision::detail::expression713 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
714 {
715 // This should always fail:
716 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
717 return *this;
718 }
719 template <class Other>
operator -=boost::multiprecision::detail::expression720 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
721 {
722 // This should always fail:
723 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
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 #endif
783
valueboost::multiprecision::detail::expression784 BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const BOOST_NOEXCEPT
785 {
786 return arg;
787 }
788
789 static const unsigned depth = 0;
790
791 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
792 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
793 //
794 // Horrible workaround for gcc-4.6.x which always prefers the template
795 // operator bool() rather than the non-template operator when converting to
796 // an arithmetic type:
797 //
798 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression799 explicit operator T() const
800 {
801 result_type r(*this);
802 return static_cast<bool>(r);
803 }
804 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression805 explicit operator T() const
806 {
807 return static_cast<T>(static_cast<result_type>(*this));
808 }
809 #else
810 template <class T
811 #ifndef __SUNPRO_CC
812 ,
813 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
814 #endif
815 >
operator Tboost::multiprecision::detail::expression816 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
817 {
818 return static_cast<T>(static_cast<result_type>(*this));
819 }
operator boolboost::multiprecision::detail::expression820 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
821 {
822 result_type r(*this);
823 return static_cast<bool>(r);
824 }
825 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression826 BOOST_MP_FORCEINLINE explicit operator void() const
827 {}
828 #endif
829 #endif
830 #else
operator unmentionable_typeboost::multiprecision::detail::expression831 operator unmentionable_type() const
832 {
833 return arg ? &unmentionable::proc : 0;
834 }
835 #endif
836
837 template <class T>
convert_toboost::multiprecision::detail::expression838 BOOST_MP_CXX14_CONSTEXPR T convert_to()
839 {
840 result_type r(*this);
841 return r.template convert_to<T>();
842 }
843
844 private:
845 typename expression_storage<Arg1>::type arg;
846 expression& operator=(const expression&);
847 };
848
849 template <class tag, class Arg1, class Arg2>
850 struct expression<tag, Arg1, Arg2, void, void>
851 {
852 typedef mpl::int_<2> arity;
853 typedef typename arg_type<Arg1>::type left_type;
854 typedef typename arg_type<Arg2>::type right_type;
855 typedef typename left_type::result_type left_result_type;
856 typedef typename right_type::result_type right_result_type;
857 typedef typename combine_expression<left_result_type, right_result_type>::type result_type;
858 typedef tag tag_type;
859
expressionboost::multiprecision::detail::expression860 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
expressionboost::multiprecision::detail::expression861 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
862
863 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
864 //
865 // If we have static_assert we can give a more useful error message
866 // than if we simply have no operator defined at all:
867 //
868 template <class Other>
operator =boost::multiprecision::detail::expression869 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
870 {
871 // This should always fail:
872 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
873 return *this;
874 }
operator ++boost::multiprecision::detail::expression875 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
876 {
877 // This should always fail:
878 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
879 return *this;
880 }
operator ++boost::multiprecision::detail::expression881 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
882 {
883 // This should always fail:
884 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
885 return *this;
886 }
operator --boost::multiprecision::detail::expression887 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
888 {
889 // This should always fail:
890 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
891 return *this;
892 }
operator --boost::multiprecision::detail::expression893 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
894 {
895 // This should always fail:
896 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
897 return *this;
898 }
899 template <class Other>
operator +=boost::multiprecision::detail::expression900 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
901 {
902 // This should always fail:
903 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
904 return *this;
905 }
906 template <class Other>
operator -=boost::multiprecision::detail::expression907 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
908 {
909 // This should always fail:
910 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
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 #endif
970
leftboost::multiprecision::detail::expression971 BOOST_MP_CXX14_CONSTEXPR left_type left() const
972 {
973 return left_type(arg1);
974 }
rightboost::multiprecision::detail::expression975 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg2); }
left_refboost::multiprecision::detail::expression976 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
right_refboost::multiprecision::detail::expression977 BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const BOOST_NOEXCEPT { return arg2; }
978
979 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
980 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
981 //
982 // Horrible workaround for gcc-4.6.x which always prefers the template
983 // operator bool() rather than the non-template operator when converting to
984 // an arithmetic type:
985 //
986 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression987 explicit operator T() const
988 {
989 result_type r(*this);
990 return static_cast<bool>(r);
991 }
992 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression993 explicit operator T() const
994 {
995 return static_cast<T>(static_cast<result_type>(*this));
996 }
997 #else
998 template <class T
999 #ifndef __SUNPRO_CC
1000 ,
1001 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
1002 #endif
1003 >
operator Tboost::multiprecision::detail::expression1004 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1005 {
1006 return static_cast<T>(static_cast<result_type>(*this));
1007 }
operator boolboost::multiprecision::detail::expression1008 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1009 {
1010 result_type r(*this);
1011 return static_cast<bool>(r);
1012 }
1013 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1014 BOOST_MP_FORCEINLINE explicit operator void() const
1015 {}
1016 #endif
1017 #endif
1018 #else
operator unmentionable_typeboost::multiprecision::detail::expression1019 operator unmentionable_type() const
1020 {
1021 result_type r(*this);
1022 return r ? &unmentionable::proc : 0;
1023 }
1024 #endif
1025 template <class T>
convert_toboost::multiprecision::detail::expression1026 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1027 {
1028 result_type r(*this);
1029 return r.template convert_to<T>();
1030 }
1031
1032 static const BOOST_MP_CXX14_CONSTEXPR unsigned left_depth = left_type::depth + 1;
1033 static const BOOST_MP_CXX14_CONSTEXPR unsigned right_depth = right_type::depth + 1;
1034 static const BOOST_MP_CXX14_CONSTEXPR unsigned depth = left_depth > right_depth ? left_depth : right_depth;
1035
1036 private:
1037 typename expression_storage<Arg1>::type arg1;
1038 typename expression_storage<Arg2>::type arg2;
1039 expression& operator=(const expression&);
1040 };
1041
1042 template <class tag, class Arg1, class Arg2, class Arg3>
1043 struct expression<tag, Arg1, Arg2, Arg3, void>
1044 {
1045 typedef mpl::int_<3> arity;
1046 typedef typename arg_type<Arg1>::type left_type;
1047 typedef typename arg_type<Arg2>::type middle_type;
1048 typedef typename arg_type<Arg3>::type right_type;
1049 typedef typename left_type::result_type left_result_type;
1050 typedef typename middle_type::result_type middle_result_type;
1051 typedef typename right_type::result_type right_result_type;
1052 typedef typename combine_expression<
1053 left_result_type,
1054 typename combine_expression<right_result_type, middle_result_type>::type>::type result_type;
1055 typedef tag tag_type;
1056
expressionboost::multiprecision::detail::expression1057 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
expressionboost::multiprecision::detail::expression1058 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
1059
1060 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1061 //
1062 // If we have static_assert we can give a more useful error message
1063 // than if we simply have no operator defined at all:
1064 //
1065 template <class Other>
operator =boost::multiprecision::detail::expression1066 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1067 {
1068 // This should always fail:
1069 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1070 return *this;
1071 }
operator ++boost::multiprecision::detail::expression1072 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1073 {
1074 // This should always fail:
1075 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1076 return *this;
1077 }
operator ++boost::multiprecision::detail::expression1078 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1079 {
1080 // This should always fail:
1081 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1082 return *this;
1083 }
operator --boost::multiprecision::detail::expression1084 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1085 {
1086 // This should always fail:
1087 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1088 return *this;
1089 }
operator --boost::multiprecision::detail::expression1090 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1091 {
1092 // This should always fail:
1093 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1094 return *this;
1095 }
1096 template <class Other>
operator +=boost::multiprecision::detail::expression1097 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1098 {
1099 // This should always fail:
1100 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1101 return *this;
1102 }
1103 template <class Other>
operator -=boost::multiprecision::detail::expression1104 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1105 {
1106 // This should always fail:
1107 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
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 #endif
1167
leftboost::multiprecision::detail::expression1168 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1169 {
1170 return left_type(arg1);
1171 }
middleboost::multiprecision::detail::expression1172 BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
rightboost::multiprecision::detail::expression1173 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg3); }
left_refboost::multiprecision::detail::expression1174 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
middle_refboost::multiprecision::detail::expression1175 BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const BOOST_NOEXCEPT { return arg2; }
right_refboost::multiprecision::detail::expression1176 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const BOOST_NOEXCEPT { return arg3; }
1177
1178 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1179 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1180 //
1181 // Horrible workaround for gcc-4.6.x which always prefers the template
1182 // operator bool() rather than the non-template operator when converting to
1183 // an arithmetic type:
1184 //
1185 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1186 explicit operator T() const
1187 {
1188 result_type r(*this);
1189 return static_cast<bool>(r);
1190 }
1191 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression1192 explicit operator T() const
1193 {
1194 return static_cast<T>(static_cast<result_type>(*this));
1195 }
1196 #else
1197 template <class T
1198 #ifndef __SUNPRO_CC
1199 ,
1200 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
1201 #endif
1202 >
operator Tboost::multiprecision::detail::expression1203 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1204 {
1205 return static_cast<T>(static_cast<result_type>(*this));
1206 }
operator boolboost::multiprecision::detail::expression1207 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1208 {
1209 result_type r(*this);
1210 return static_cast<bool>(r);
1211 }
1212 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1213 BOOST_MP_FORCEINLINE explicit operator void() const
1214 {}
1215 #endif
1216 #endif
1217 #else
operator unmentionable_typeboost::multiprecision::detail::expression1218 operator unmentionable_type() const
1219 {
1220 result_type r(*this);
1221 return r ? &unmentionable::proc : 0;
1222 }
1223 #endif
1224 template <class T>
convert_toboost::multiprecision::detail::expression1225 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1226 {
1227 result_type r(*this);
1228 return r.template convert_to<T>();
1229 }
1230
1231 static const unsigned left_depth = left_type::depth + 1;
1232 static const unsigned middle_depth = middle_type::depth + 1;
1233 static const unsigned right_depth = right_type::depth + 1;
1234 static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
1235
1236 private:
1237 typename expression_storage<Arg1>::type arg1;
1238 typename expression_storage<Arg2>::type arg2;
1239 typename expression_storage<Arg3>::type arg3;
1240 expression& operator=(const expression&);
1241 };
1242
1243 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1244 struct expression
1245 {
1246 typedef mpl::int_<4> arity;
1247 typedef typename arg_type<Arg1>::type left_type;
1248 typedef typename arg_type<Arg2>::type left_middle_type;
1249 typedef typename arg_type<Arg3>::type right_middle_type;
1250 typedef typename arg_type<Arg4>::type right_type;
1251 typedef typename left_type::result_type left_result_type;
1252 typedef typename left_middle_type::result_type left_middle_result_type;
1253 typedef typename right_middle_type::result_type right_middle_result_type;
1254 typedef typename right_type::result_type right_result_type;
1255 typedef typename combine_expression<
1256 left_result_type,
1257 typename combine_expression<
1258 left_middle_result_type,
1259 typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type result_type;
1260 typedef tag tag_type;
1261
expressionboost::multiprecision::detail::expression1262 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::expression1263 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
1264
1265 #ifndef BOOST_NO_CXX11_STATIC_ASSERT
1266 //
1267 // If we have static_assert we can give a more useful error message
1268 // than if we simply have no operator defined at all:
1269 //
1270 template <class Other>
operator =boost::multiprecision::detail::expression1271 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1272 {
1273 // This should always fail:
1274 static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1275 return *this;
1276 }
operator ++boost::multiprecision::detail::expression1277 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1278 {
1279 // This should always fail:
1280 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1281 return *this;
1282 }
operator ++boost::multiprecision::detail::expression1283 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1284 {
1285 // This should always fail:
1286 static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1287 return *this;
1288 }
operator --boost::multiprecision::detail::expression1289 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1290 {
1291 // This should always fail:
1292 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1293 return *this;
1294 }
operator --boost::multiprecision::detail::expression1295 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1296 {
1297 // This should always fail:
1298 static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1299 return *this;
1300 }
1301 template <class Other>
operator +=boost::multiprecision::detail::expression1302 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1303 {
1304 // This should always fail:
1305 static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
1306 return *this;
1307 }
1308 template <class Other>
operator -=boost::multiprecision::detail::expression1309 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1310 {
1311 // This should always fail:
1312 static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
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 #endif
1372
leftboost::multiprecision::detail::expression1373 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1374 {
1375 return left_type(arg1);
1376 }
left_middleboost::multiprecision::detail::expression1377 BOOST_MP_CXX14_CONSTEXPR left_middle_type left_middle() const { return left_middle_type(arg2); }
right_middleboost::multiprecision::detail::expression1378 BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
rightboost::multiprecision::detail::expression1379 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg4); }
left_refboost::multiprecision::detail::expression1380 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
left_middle_refboost::multiprecision::detail::expression1381 BOOST_MP_CXX14_CONSTEXPR const Arg2& left_middle_ref() const BOOST_NOEXCEPT { return arg2; }
right_middle_refboost::multiprecision::detail::expression1382 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_middle_ref() const BOOST_NOEXCEPT { return arg3; }
right_refboost::multiprecision::detail::expression1383 BOOST_MP_CXX14_CONSTEXPR const Arg4& right_ref() const BOOST_NOEXCEPT { return arg4; }
1384
1385 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
1386 #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
1387 //
1388 // Horrible workaround for gcc-4.6.x which always prefers the template
1389 // operator bool() rather than the non-template operator when converting to
1390 // an arithmetic type:
1391 //
1392 template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression1393 explicit operator T() const
1394 {
1395 result_type r(*this);
1396 return static_cast<bool>(r);
1397 }
1398 template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression1399 explicit operator T() const
1400 {
1401 return static_cast<T>(static_cast<result_type>(*this));
1402 }
1403 #else
1404 template <class T
1405 #ifndef __SUNPRO_CC
1406 ,
1407 typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
1408 #endif
1409 >
operator Tboost::multiprecision::detail::expression1410 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1411 {
1412 return static_cast<T>(static_cast<result_type>(*this));
1413 }
operator boolboost::multiprecision::detail::expression1414 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1415 {
1416 result_type r(*this);
1417 return static_cast<bool>(r);
1418 }
1419 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression1420 BOOST_MP_FORCEINLINE explicit operator void() const
1421 {}
1422 #endif
1423 #endif
1424 #else
operator unmentionable_typeboost::multiprecision::detail::expression1425 operator unmentionable_type() const
1426 {
1427 result_type r(*this);
1428 return r ? &unmentionable::proc : 0;
1429 }
1430 #endif
1431 template <class T>
convert_toboost::multiprecision::detail::expression1432 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1433 {
1434 result_type r(*this);
1435 return r.template convert_to<T>();
1436 }
1437
1438 static const unsigned left_depth = left_type::depth + 1;
1439 static const unsigned left_middle_depth = left_middle_type::depth + 1;
1440 static const unsigned right_middle_depth = right_middle_type::depth + 1;
1441 static const unsigned right_depth = right_type::depth + 1;
1442
1443 static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
1444 static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
1445
1446 static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
1447
1448 private:
1449 typename expression_storage<Arg1>::type arg1;
1450 typename expression_storage<Arg2>::type arg2;
1451 typename expression_storage<Arg3>::type arg3;
1452 typename expression_storage<Arg4>::type arg4;
1453 expression& operator=(const expression&);
1454 };
1455
1456 template <class T>
1457 struct digits2
1458 {
1459 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
1460 BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
1461 // If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
1462 BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
1463 static const long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
valueboost::multiprecision::detail::digits21464 static inline BOOST_CONSTEXPR long value() BOOST_NOEXCEPT { return m_value; }
1465 };
1466
1467 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
1468 #ifdef _MSC_VER
1469 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1470 #else
1471 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1472 #endif
1473 #endif
1474
1475 template <class S>
format_float_string(S & str,boost::intmax_t my_exp,boost::intmax_t digits,std::ios_base::fmtflags f,bool iszero)1476 void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
1477 {
1478 typedef typename S::size_type size_type;
1479 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
1480 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
1481 bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
1482 bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
1483
1484 bool neg = str.size() && (str[0] == '-');
1485
1486 if (neg)
1487 str.erase(0, 1);
1488
1489 if (digits == 0)
1490 {
1491 digits = (std::max)(str.size(), size_type(16));
1492 }
1493
1494 if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
1495 {
1496 // We will be printing zero, even though the value might not
1497 // actually be zero (it just may have been rounded to zero).
1498 str = "0";
1499 if (scientific || fixed)
1500 {
1501 str.append(1, '.');
1502 str.append(size_type(digits), '0');
1503 if (scientific)
1504 str.append("e+00");
1505 }
1506 else
1507 {
1508 if (showpoint)
1509 {
1510 str.append(1, '.');
1511 if (digits > 1)
1512 str.append(size_type(digits - 1), '0');
1513 }
1514 }
1515 if (neg)
1516 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1517 else if (showpos)
1518 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1519 return;
1520 }
1521
1522 if (!fixed && !scientific && !showpoint)
1523 {
1524 //
1525 // Suppress trailing zeros:
1526 //
1527 std::string::iterator pos = str.end();
1528 while (pos != str.begin() && *--pos == '0')
1529 {
1530 }
1531 if (pos != str.end())
1532 ++pos;
1533 str.erase(pos, str.end());
1534 if (str.empty())
1535 str = '0';
1536 }
1537 else if (!fixed || (my_exp >= 0))
1538 {
1539 //
1540 // Pad out the end with zero's if we need to:
1541 //
1542 boost::intmax_t chars = str.size();
1543 chars = digits - chars;
1544 if (scientific)
1545 ++chars;
1546 if (chars > 0)
1547 {
1548 str.append(static_cast<std::string::size_type>(chars), '0');
1549 }
1550 }
1551
1552 if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
1553 {
1554 if (1 + my_exp > static_cast<boost::intmax_t>(str.size()))
1555 {
1556 // Just pad out the end with zeros:
1557 str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
1558 if (showpoint || fixed)
1559 str.append(".");
1560 }
1561 else if (my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
1562 {
1563 if (my_exp < 0)
1564 {
1565 str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
1566 str.insert(static_cast<std::string::size_type>(0), "0.");
1567 }
1568 else
1569 {
1570 // Insert the decimal point:
1571 str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
1572 }
1573 }
1574 else if (showpoint || fixed) // we have exactly the digits we require to left of the point
1575 str += ".";
1576
1577 if (fixed)
1578 {
1579 // We may need to add trailing zeros:
1580 boost::intmax_t l = str.find('.') + 1;
1581 l = digits - (str.size() - l);
1582 if (l > 0)
1583 str.append(size_type(l), '0');
1584 }
1585 }
1586 else
1587 {
1588 BOOST_MP_USING_ABS
1589 // Scientific format:
1590 if (showpoint || (str.size() > 1))
1591 str.insert(static_cast<std::string::size_type>(1u), 1, '.');
1592 str.append(static_cast<std::string::size_type>(1u), 'e');
1593 S e = boost::lexical_cast<S>(abs(my_exp));
1594 if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
1595 e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
1596 if (my_exp < 0)
1597 e.insert(static_cast<std::string::size_type>(0), 1, '-');
1598 else
1599 e.insert(static_cast<std::string::size_type>(0), 1, '+');
1600 str.append(e);
1601 }
1602 if (neg)
1603 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1604 else if (showpos)
1605 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1606 }
1607
1608 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::true_ &)1609 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
1610 {
1611 if (val > (std::numeric_limits<std::size_t>::max)())
1612 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1613 if (val < 0)
1614 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1615 }
1616 template <class V>
check_shift_range(V val,const mpl::false_ &,const mpl::true_ &)1617 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
1618 {
1619 if (val < 0)
1620 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1621 }
1622 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::false_ &)1623 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
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 }
1628 template <class V>
check_shift_range(V,const mpl::false_ &,const mpl::false_ &)1629 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT {}
1630
1631 template <class T>
evaluate_if_expression(const T & val)1632 BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
1633 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
evaluate_if_expression(const expression<tag,Arg1,Arg2,Arg3,Arg4> & val)1634 BOOST_MP_CXX14_CONSTEXPR typename expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type evaluate_if_expression(const expression<tag, Arg1, Arg2, Arg3, Arg4>& val) { return val; }
1635
1636 } // namespace detail
1637
1638 //
1639 // Traits class, lets us know what kind of number we have, defaults to a floating point type:
1640 //
1641 enum number_category_type
1642 {
1643 number_kind_unknown = -1,
1644 number_kind_integer = 0,
1645 number_kind_floating_point = 1,
1646 number_kind_rational = 2,
1647 number_kind_fixed_point = 3,
1648 number_kind_complex = 4
1649 };
1650
1651 template <class Num, bool, bool>
1652 struct number_category_base : public mpl::int_<number_kind_unknown>
1653 {};
1654 template <class Num>
1655 struct number_category_base<Num, true, false> : public mpl::int_<std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)>
1656 {};
1657 template <class Num>
1658 struct number_category : public number_category_base<Num, boost::is_class<Num>::value || boost::is_arithmetic<Num>::value, boost::is_abstract<Num>::value>
1659 {};
1660 template <class Backend, expression_template_option ExpressionTemplates>
1661 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
1662 {};
1663 template <class tag, class A1, class A2, class A3, class A4>
1664 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1665 {};
1666 //
1667 // Specializations for types which do not always have numberic_limits specializations:
1668 //
1669 #ifdef BOOST_HAS_INT128
1670 template <>
1671 struct number_category<boost::int128_type> : public mpl::int_<number_kind_integer>
1672 {};
1673 template <>
1674 struct number_category<boost::uint128_type> : public mpl::int_<number_kind_integer>
1675 {};
1676 #endif
1677 #ifdef BOOST_HAS_FLOAT128
1678 template <>
1679 struct number_category<__float128> : public mpl::int_<number_kind_floating_point>
1680 {};
1681 #endif
1682
1683 template <class T>
1684 struct component_type
1685 {
1686 typedef T type;
1687 };
1688 template <class tag, class A1, class A2, class A3, class A4>
1689 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1690 {};
1691
1692 template <class T>
1693 struct scalar_result_from_possible_complex
1694 {
1695 typedef typename mpl::if_c<number_category<T>::value == number_kind_complex,
1696 typename component_type<T>::type, T>::type type;
1697 };
1698
1699 template <class T>
1700 struct complex_result_from_scalar; // individual backends must specialize this trait.
1701
1702 template <class T>
1703 struct is_unsigned_number : public mpl::false_
1704 {};
1705 template <class Backend, expression_template_option ExpressionTemplates>
1706 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
1707 {};
1708 template <class T>
1709 struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value>
1710 {};
1711 template <class T>
1712 struct is_interval_number : public mpl::false_
1713 {};
1714 template <class Backend, expression_template_option ExpressionTemplates>
1715 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
1716 {};
1717
1718 } // namespace multiprecision
1719 } // namespace boost
1720
1721 namespace boost { namespace math {
1722 namespace tools {
1723
1724 template <class T>
1725 struct promote_arg;
1726
1727 template <class tag, class A1, class A2, class A3, class A4>
1728 struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
1729 {
1730 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
1731 };
1732
1733 template <class R, class B, boost::multiprecision::expression_template_option ET>
real_cast(const boost::multiprecision::number<B,ET> & val)1734 inline R real_cast(const boost::multiprecision::number<B, ET>& val)
1735 {
1736 return val.template convert_to<R>();
1737 }
1738
1739 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)1740 inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
1741 {
1742 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
1743 return val_type(val).template convert_to<R>();
1744 }
1745
1746 template <class B, boost::multiprecision::expression_template_option ET>
1747 struct is_complex_type<boost::multiprecision::number<B, ET> > : public boost::mpl::bool_<boost::multiprecision::number_category<B>::value == boost::multiprecision::number_kind_complex> {};
1748
1749 } // namespace tools
1750
1751 namespace constants {
1752
1753 template <class T>
1754 struct is_explicitly_convertible_from_string;
1755
1756 template <class B, boost::multiprecision::expression_template_option ET>
1757 struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
1758 {
1759 static const bool value = true;
1760 };
1761
1762 } // namespace constants
1763
1764 }} // namespace boost::math
1765
1766 #ifdef BOOST_MSVC
1767 #pragma warning(pop)
1768 #endif
1769
1770 #endif // BOOST_MATH_BIG_NUM_BASE_HPP
1771