File indexing completed on 2025-07-03 08:21:05
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MP_NUMBER_BASE_HPP
0007 #define BOOST_MP_NUMBER_BASE_HPP
0008
0009 #include <climits>
0010 #include <ios>
0011 #include <string>
0012 #include <limits>
0013 #include <type_traits>
0014 #include <stdexcept>
0015 #include <tuple>
0016 #include <boost/multiprecision/detail/standalone_config.hpp>
0017 #include <boost/multiprecision/fwd.hpp>
0018 #include <boost/multiprecision/traits/transcendental_reduction_type.hpp>
0019 #include <boost/multiprecision/traits/std_integer_traits.hpp>
0020 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0021
0022 #ifdef BOOST_MSVC
0023 #pragma warning(push)
0024 #pragma warning(disable : 4307)
0025 #pragma warning(pop)
0026 #endif
0027
0028 #ifndef BOOST_MP_STANDALONE
0029 #include <boost/lexical_cast.hpp>
0030 #include <boost/core/nvp.hpp>
0031 #endif
0032
0033 #ifdef BOOST_MP_MATH_AVAILABLE
0034 #include <boost/math/tools/complex.hpp>
0035 #endif
0036
0037
0038 #include <boost/multiprecision/detail/check_cpp11_config.hpp>
0039
0040 #if defined(NDEBUG) && !defined(_DEBUG)
0041 #define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE
0042 #else
0043 #define BOOST_MP_FORCEINLINE inline
0044 #endif
0045
0046
0047
0048
0049
0050 #if defined(BOOST_NO_CXX11_THREAD_LOCAL)
0051 #define BOOST_MP_THREAD_LOCAL
0052 #elif !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ < 9)) && !defined(__clang__))
0053 #define BOOST_MP_THREAD_LOCAL thread_local
0054 #define BOOST_MP_USING_THREAD_LOCAL
0055 #else
0056 #pragma GCC warning "thread_local on mingw is broken, please use MSys mingw gcc-9 or later, see https://sourceforge.net/p/mingw-w64/bugs/527/"
0057 #define BOOST_MP_THREAD_LOCAL
0058 #endif
0059
0060 #ifdef __has_include
0061 # if __has_include(<version>)
0062 # include <version>
0063 # ifdef __cpp_lib_is_constant_evaluated
0064 # include <type_traits>
0065 # define BOOST_MP_HAS_IS_CONSTANT_EVALUATED
0066 # endif
0067 # endif
0068 #endif
0069
0070 #ifdef __has_builtin
0071 #if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
0072 #define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
0073 #endif
0074 #endif
0075
0076
0077
0078 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 192528326)
0079 # define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
0080 #endif
0081
0082
0083
0084 #if defined(BOOST_GCC) && !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9) && !defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
0085 # define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
0086 #endif
0087
0088 #if defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
0089 # define BOOST_MP_IS_CONST_EVALUATED(x) std::is_constant_evaluated()
0090 #elif defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
0091 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_is_constant_evaluated()
0092 #elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_GCC) && (__GNUC__ >= 6)
0093 # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_constant_p(x)
0094 #else
0095 # define BOOST_MP_NO_CONSTEXPR_DETECTION
0096 #endif
0097
0098
0099 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
0100 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION
0101 #else
0102 # define BOOST_CXX14_CONSTEXPR_IF_DETECTION constexpr
0103 #endif
0104
0105 #ifdef BOOST_MSVC
0106 #pragma warning(push)
0107 #pragma warning(disable : 6326)
0108 #endif
0109
0110 namespace boost {
0111 namespace multiprecision {
0112
0113
0114 enum struct variable_precision_options : signed char
0115 {
0116 assume_uniform_precision = -1,
0117 preserve_target_precision = 0,
0118 preserve_source_precision = 1,
0119 preserve_component_precision = 2,
0120 preserve_related_precision = 3,
0121 preserve_all_precision = 4,
0122 };
0123
0124 inline constexpr bool operator==(variable_precision_options a, variable_precision_options b)
0125 {
0126 return static_cast<unsigned>(a) == static_cast<unsigned>(b);
0127 }
0128
0129 template <class T>
0130 struct is_et_number : public std::integral_constant<bool, false>
0131 {};
0132
0133 template <class Backend>
0134 struct is_et_number<number<Backend, et_on> > : public std::integral_constant<bool, true>
0135 {};
0136
0137 template <class T>
0138 struct is_no_et_number : public std::integral_constant<bool, false>
0139 {};
0140
0141 template <class Backend>
0142 struct is_no_et_number<number<Backend, et_off> > : public std::integral_constant<bool, true>
0143 {};
0144
0145 template <class T>
0146 struct is_number_expression : public std::integral_constant<bool, false>
0147 {};
0148
0149 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0150 struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public std::integral_constant<bool, true>
0151 {};
0152
0153 namespace detail {
0154 template <class Val, class Backend>
0155 struct canonical;
0156 }
0157
0158 template <class T, class Num>
0159 struct is_compatible_arithmetic_type
0160 : public std::integral_constant<bool,
0161 std::is_convertible<T, Num>::value && !std::is_same<T, Num>::value && !is_number_expression<T>::value
0162 && (std::is_constructible<typename Num::backend_type, typename detail::canonical<T, typename Num::backend_type>::type>::value
0163 || std::is_assignable<typename Num::backend_type, typename detail::canonical<T, typename Num::backend_type>::type>::value || is_number<T>::value || is_number_expression<T>::value)>
0164 {};
0165
0166 namespace detail {
0167
0168
0169
0170 template <class T>
0171 constexpr typename std::enable_if<(boost::multiprecision::detail::is_signed<T>::value || std::is_floating_point<T>::value), T>::type abs(T t) noexcept
0172 {
0173
0174
0175
0176 return t < 0 ? T(1u) + T(-(t + 1)) : t;
0177 }
0178 template <class T>
0179 constexpr typename std::enable_if<boost::multiprecision::detail::is_unsigned<T>::value, T>::type abs(T t) noexcept
0180 {
0181 return t;
0182 }
0183
0184 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
0185
0186 template <class T>
0187 constexpr typename std::enable_if<(boost::multiprecision::detail::is_signed<T>::value || std::is_floating_point<T>::value), typename boost::multiprecision::detail::make_unsigned<T>::type>::type unsigned_abs(T t) noexcept
0188 {
0189
0190
0191
0192 return t < 0 ? static_cast<typename boost::multiprecision::detail::make_unsigned<T>::type>(1u) + static_cast<typename boost::multiprecision::detail::make_unsigned<T>::type>(-(t + 1)) : static_cast<typename boost::multiprecision::detail::make_unsigned<T>::type>(t);
0193 }
0194 template <class T>
0195 constexpr typename std::enable_if<boost::multiprecision::detail::is_unsigned<T>::value, T>::type unsigned_abs(T t) noexcept
0196 {
0197 return t;
0198 }
0199
0200 template <class T>
0201 struct bits_of
0202 {
0203 static_assert(boost::multiprecision::detail::is_integral<T>::value || std::is_enum<T>::value || std::numeric_limits<T>::is_specialized, "Failed integer size check");
0204 static constexpr unsigned value =
0205 std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
0206 : sizeof(T) * CHAR_BIT - (boost::multiprecision::detail::is_signed<T>::value ? 1 : 0);
0207 };
0208
0209 #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
0210 #define BOOST_MP_BITS_OF_FLOAT128_DEFINED
0211 template <>
0212 struct bits_of<float128_type>
0213 {
0214 static constexpr unsigned value = 113;
0215 };
0216 #endif
0217
0218 template <int b>
0219 struct has_enough_bits
0220 {
0221 template <class T>
0222 struct type : public std::integral_constant<bool, bits_of<T>::value >= b>
0223 {};
0224 };
0225
0226 template <class Tuple, int i, int digits, bool = (i >= std::tuple_size<Tuple>::value)>
0227 struct find_index_of_large_enough_type
0228 {
0229 static constexpr int value = bits_of<typename std::tuple_element<static_cast<std::size_t>(i), Tuple>::type>::value >= digits ? i : find_index_of_large_enough_type<Tuple, i + 1, digits>::value;
0230 };
0231 template <class Tuple, int i, int digits>
0232 struct find_index_of_large_enough_type<Tuple, i, digits, true>
0233 {
0234 static constexpr int value = INT_MAX;
0235 };
0236
0237 template <int index, class Tuple, class Fallback, bool = (std::tuple_size<Tuple>::value <= index)>
0238 struct dereference_tuple
0239 {
0240 using type = typename std::tuple_element<static_cast<std::size_t>(index), Tuple>::type;
0241 };
0242 template <int index, class Tuple, class Fallback>
0243 struct dereference_tuple<index, Tuple, Fallback, true>
0244 {
0245 using type = Fallback;
0246 };
0247
0248 template <class Val, class Backend, class Tag>
0249 struct canonical_imp
0250 {
0251 using type = typename std::remove_cv<typename std::decay<const Val>::type>::type;
0252 };
0253 template <class B, class Backend, class Tag>
0254 struct canonical_imp<number<B, et_on>, Backend, Tag>
0255 {
0256 using type = B;
0257 };
0258 template <class B, class Backend, class Tag>
0259 struct canonical_imp<number<B, et_off>, Backend, Tag>
0260 {
0261 using type = B;
0262 };
0263 #ifdef __SUNPRO_CC
0264 template <class B, class Backend>
0265 struct canonical_imp<number<B, et_on>, Backend, std::integral_constant<int, 3> >
0266 {
0267 using type = B;
0268 };
0269 template <class B, class Backend>
0270 struct canonical_imp<number<B, et_off>, Backend, std::integral_constant<int, 3> >
0271 {
0272 using type = B;
0273 };
0274 #endif
0275 template <class Val, class Backend>
0276 struct canonical_imp<Val, Backend, std::integral_constant<int, 0> >
0277 {
0278 static constexpr int index = find_index_of_large_enough_type<typename Backend::signed_types, 0, bits_of<Val>::value>::value;
0279 using type = typename dereference_tuple<index, typename Backend::signed_types, Val>::type;
0280 };
0281 template <class Val, class Backend>
0282 struct canonical_imp<Val, Backend, std::integral_constant<int, 1> >
0283 {
0284 static constexpr int index = find_index_of_large_enough_type<typename Backend::unsigned_types, 0, bits_of<Val>::value>::value;
0285 using type = typename dereference_tuple<index, typename Backend::unsigned_types, Val>::type;
0286 };
0287 template <class Val, class Backend>
0288 struct canonical_imp<Val, Backend, std::integral_constant<int, 2> >
0289 {
0290 static constexpr int index = find_index_of_large_enough_type<typename Backend::float_types, 0, bits_of<Val>::value>::value;
0291 using type = typename dereference_tuple<index, typename Backend::float_types, Val>::type;
0292 };
0293 template <class Val, class Backend>
0294 struct canonical_imp<Val, Backend, std::integral_constant<int, 3> >
0295 {
0296 using type = const char*;
0297 };
0298 template <class Val, class Backend>
0299 struct canonical_imp<Val, Backend, std::integral_constant<int, 4> >
0300 {
0301 using underlying = typename std::underlying_type<Val>::type;
0302 using tag = typename std::conditional<boost::multiprecision::detail::is_signed<Val>::value, std::integral_constant<int, 0>, std::integral_constant<int, 1>>::type;
0303 using type = typename canonical_imp<underlying, Backend, tag>::type;
0304 };
0305
0306 template <class Val, class Backend>
0307 struct canonical
0308 {
0309 using tag_type = typename std::conditional<
0310 boost::multiprecision::detail::is_signed<Val>::value && boost::multiprecision::detail::is_integral<Val>::value,
0311 std::integral_constant<int, 0>,
0312 typename std::conditional<
0313 boost::multiprecision::detail::is_unsigned<Val>::value,
0314 std::integral_constant<int, 1>,
0315 typename std::conditional<
0316 std::is_floating_point<Val>::value,
0317 std::integral_constant<int, 2>,
0318 typename std::conditional<
0319 (std::is_convertible<Val, const char*>::value || std::is_same<Val, std::string>::value),
0320 std::integral_constant<int, 3>,
0321 typename std::conditional<
0322 std::is_enum<Val>::value,
0323 std::integral_constant<int, 4>,
0324 std::integral_constant<int, 5> >::type>::type>::type>::type>::type;
0325
0326 using type = typename canonical_imp<Val, Backend, tag_type>::type;
0327 };
0328
0329 struct terminal
0330 {};
0331 struct negate
0332 {};
0333 struct plus
0334 {};
0335 struct minus
0336 {};
0337 struct multiplies
0338 {};
0339 struct divides
0340 {};
0341 struct modulus
0342 {};
0343 struct shift_left
0344 {};
0345 struct shift_right
0346 {};
0347 struct bitwise_and
0348 {};
0349 struct bitwise_or
0350 {};
0351 struct bitwise_xor
0352 {};
0353 struct bitwise_complement
0354 {};
0355 struct add_immediates
0356 {};
0357 struct subtract_immediates
0358 {};
0359 struct multiply_immediates
0360 {};
0361 struct divide_immediates
0362 {};
0363 struct modulus_immediates
0364 {};
0365 struct bitwise_and_immediates
0366 {};
0367 struct bitwise_or_immediates
0368 {};
0369 struct bitwise_xor_immediates
0370 {};
0371 struct complement_immediates
0372 {};
0373 struct function
0374 {};
0375 struct multiply_add
0376 {};
0377 struct multiply_subtract
0378 {};
0379
0380 template <class T>
0381 struct backend_type;
0382
0383 template <class T, expression_template_option ExpressionTemplates>
0384 struct backend_type<number<T, ExpressionTemplates> >
0385 {
0386 using type = T;
0387 };
0388
0389 template <class tag, class A1, class A2, class A3, class A4>
0390 struct backend_type<expression<tag, A1, A2, A3, A4> >
0391 {
0392 using type = typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type;
0393 };
0394
0395 template <class T1, class T2>
0396 struct combine_expression
0397 {
0398 using type = decltype(T1() + T2());
0399 };
0400
0401 template <class T1, expression_template_option ExpressionTemplates, class T2>
0402 struct combine_expression<number<T1, ExpressionTemplates>, T2>
0403 {
0404 using type = number<T1, ExpressionTemplates>;
0405 };
0406
0407 template <class T1, class T2, expression_template_option ExpressionTemplates>
0408 struct combine_expression<T1, number<T2, ExpressionTemplates> >
0409 {
0410 using type = number<T2, ExpressionTemplates>;
0411 };
0412
0413 template <class T, expression_template_option ExpressionTemplates>
0414 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
0415 {
0416 using type = number<T, ExpressionTemplates>;
0417 };
0418
0419 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
0420 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
0421 {
0422 using type = typename std::conditional<
0423 std::is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
0424 number<T1, ExpressionTemplates1>,
0425 number<T2, ExpressionTemplates2> >::type;
0426 };
0427
0428 template <class T>
0429 struct arg_type
0430 {
0431 using type = expression<terminal, T>;
0432 };
0433
0434 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
0435 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
0436 {
0437 using type = expression<Tag, Arg1, Arg2, Arg3, Arg4>;
0438 };
0439
0440 struct unmentionable
0441 {
0442 unmentionable* proc() { return nullptr; }
0443 };
0444
0445 typedef unmentionable* (unmentionable::*unmentionable_type)();
0446
0447 template <class T, bool b>
0448 struct expression_storage_base
0449 {
0450 using type = const T&;
0451 };
0452
0453 template <class T>
0454 struct expression_storage_base<T, true>
0455 {
0456 using type = T;
0457 };
0458
0459 template <class T>
0460 struct expression_storage : public expression_storage_base<T, boost::multiprecision::detail::is_arithmetic<T>::value>
0461 {};
0462
0463 template <class T>
0464 struct expression_storage<T*>
0465 {
0466 using type = T*;
0467 };
0468
0469 template <class T>
0470 struct expression_storage<const T*>
0471 {
0472 using type = const T*;
0473 };
0474
0475 template <class tag, class A1, class A2, class A3, class A4>
0476 struct expression_storage<expression<tag, A1, A2, A3, A4> >
0477 {
0478 using type = expression<tag, A1, A2, A3, A4>;
0479 };
0480
0481 template <class tag, class Arg1>
0482 struct expression<tag, Arg1, void, void, void>
0483 {
0484 using arity = std::integral_constant<int, 1> ;
0485 using left_type = typename arg_type<Arg1>::type ;
0486 using left_result_type = typename left_type::result_type;
0487 using result_type = typename left_type::result_type;
0488 using tag_type = tag ;
0489
0490 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
0491 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
0492
0493
0494
0495
0496
0497 template <class Other>
0498 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0499 {
0500
0501 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?");
0502 return *this;
0503 }
0504 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0505 {
0506
0507 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?");
0508 return *this;
0509 }
0510 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0511 {
0512
0513 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?");
0514 return *this;
0515 }
0516 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0517 {
0518
0519 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?");
0520 return *this;
0521 }
0522 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0523 {
0524
0525 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?");
0526 return *this;
0527 }
0528 template <class Other>
0529 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
0530 {
0531
0532 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?");
0533 return *this;
0534 }
0535 template <class Other>
0536 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
0537 {
0538
0539 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?");
0540 return *this;
0541 }
0542 template <class Other>
0543 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
0544 {
0545
0546 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?");
0547 return *this;
0548 }
0549 template <class Other>
0550 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
0551 {
0552
0553 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?");
0554 return *this;
0555 }
0556 template <class Other>
0557 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
0558 {
0559
0560 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?");
0561 return *this;
0562 }
0563 template <class Other>
0564 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
0565 {
0566
0567 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?");
0568 return *this;
0569 }
0570 template <class Other>
0571 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
0572 {
0573
0574 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?");
0575 return *this;
0576 }
0577 template <class Other>
0578 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
0579 {
0580
0581 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?");
0582 return *this;
0583 }
0584 template <class Other>
0585 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
0586 {
0587
0588 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?");
0589 return *this;
0590 }
0591 template <class Other>
0592 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
0593 {
0594
0595 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?");
0596 return *this;
0597 }
0598
0599 BOOST_MP_CXX14_CONSTEXPR left_type left() const
0600 {
0601 return left_type(arg);
0602 }
0603
0604 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg; }
0605
0606 static constexpr unsigned depth = left_type::depth + 1;
0607 template <class T
0608 #ifndef __SUNPRO_CC
0609 ,
0610 typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
0611 #endif
0612 >
0613 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
0614 {
0615 return static_cast<T>(static_cast<result_type>(*this));
0616 }
0617 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
0618 {
0619 result_type r(*this);
0620 return static_cast<bool>(r);
0621 }
0622
0623 template <class T>
0624 BOOST_MP_CXX14_CONSTEXPR T convert_to()
0625 {
0626 result_type r(*this);
0627 return r.template convert_to<T>();
0628 }
0629
0630 private:
0631 typename expression_storage<Arg1>::type arg;
0632 expression& operator=(const expression&);
0633 };
0634
0635 template <class Arg1>
0636 struct expression<terminal, Arg1, void, void, void>
0637 {
0638 using arity = std::integral_constant<int, 0>;
0639 using result_type = Arg1 ;
0640 using tag_type = terminal ;
0641
0642 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
0643 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
0644
0645
0646
0647
0648
0649 template <class Other>
0650 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0651 {
0652
0653 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?");
0654 return *this;
0655 }
0656 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0657 {
0658
0659 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?");
0660 return *this;
0661 }
0662 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0663 {
0664
0665 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?");
0666 return *this;
0667 }
0668 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0669 {
0670
0671 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?");
0672 return *this;
0673 }
0674 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0675 {
0676
0677 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?");
0678 return *this;
0679 }
0680 template <class Other>
0681 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
0682 {
0683
0684 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?");
0685 return *this;
0686 }
0687 template <class Other>
0688 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
0689 {
0690
0691 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?");
0692 return *this;
0693 }
0694 template <class Other>
0695 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
0696 {
0697
0698 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?");
0699 return *this;
0700 }
0701 template <class Other>
0702 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
0703 {
0704
0705 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?");
0706 return *this;
0707 }
0708 template <class Other>
0709 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
0710 {
0711
0712 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?");
0713 return *this;
0714 }
0715 template <class Other>
0716 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
0717 {
0718
0719 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?");
0720 return *this;
0721 }
0722 template <class Other>
0723 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
0724 {
0725
0726 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?");
0727 return *this;
0728 }
0729 template <class Other>
0730 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
0731 {
0732
0733 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?");
0734 return *this;
0735 }
0736 template <class Other>
0737 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
0738 {
0739
0740 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?");
0741 return *this;
0742 }
0743 template <class Other>
0744 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
0745 {
0746
0747 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?");
0748 return *this;
0749 }
0750
0751 BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const noexcept
0752 {
0753 return arg;
0754 }
0755
0756 static constexpr unsigned depth = 0;
0757
0758 template <class T
0759 #ifndef __SUNPRO_CC
0760 ,
0761 typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
0762 #endif
0763 >
0764 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
0765 {
0766 return static_cast<T>(static_cast<result_type>(*this));
0767 }
0768 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
0769 {
0770 result_type r(*this);
0771 return static_cast<bool>(r);
0772 }
0773
0774 template <class T>
0775 BOOST_MP_CXX14_CONSTEXPR T convert_to()
0776 {
0777 result_type r(*this);
0778 return r.template convert_to<T>();
0779 }
0780
0781 private:
0782 typename expression_storage<Arg1>::type arg;
0783 expression& operator=(const expression&);
0784 };
0785
0786 template <class tag, class Arg1, class Arg2>
0787 struct expression<tag, Arg1, Arg2, void, void>
0788 {
0789 using arity = std::integral_constant<int, 2> ;
0790 using left_type = typename arg_type<Arg1>::type ;
0791 using right_type = typename arg_type<Arg2>::type ;
0792 using left_result_type = typename left_type::result_type ;
0793 using right_result_type = typename right_type::result_type ;
0794 using result_type = typename combine_expression<left_result_type, right_result_type>::type;
0795 using tag_type = tag ;
0796
0797 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
0798 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
0799
0800
0801
0802
0803
0804 template <class Other>
0805 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0806 {
0807
0808 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?");
0809 return *this;
0810 }
0811 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0812 {
0813
0814 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?");
0815 return *this;
0816 }
0817 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0818 {
0819
0820 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?");
0821 return *this;
0822 }
0823 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0824 {
0825
0826 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?");
0827 return *this;
0828 }
0829 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0830 {
0831
0832 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?");
0833 return *this;
0834 }
0835 template <class Other>
0836 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
0837 {
0838
0839 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?");
0840 return *this;
0841 }
0842 template <class Other>
0843 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
0844 {
0845
0846 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?");
0847 return *this;
0848 }
0849 template <class Other>
0850 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
0851 {
0852
0853 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?");
0854 return *this;
0855 }
0856 template <class Other>
0857 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
0858 {
0859
0860 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?");
0861 return *this;
0862 }
0863 template <class Other>
0864 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
0865 {
0866
0867 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?");
0868 return *this;
0869 }
0870 template <class Other>
0871 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
0872 {
0873
0874 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?");
0875 return *this;
0876 }
0877 template <class Other>
0878 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
0879 {
0880
0881 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?");
0882 return *this;
0883 }
0884 template <class Other>
0885 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
0886 {
0887
0888 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?");
0889 return *this;
0890 }
0891 template <class Other>
0892 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
0893 {
0894
0895 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?");
0896 return *this;
0897 }
0898 template <class Other>
0899 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
0900 {
0901
0902 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?");
0903 return *this;
0904 }
0905
0906 BOOST_MP_CXX14_CONSTEXPR left_type left() const
0907 {
0908 return left_type(arg1);
0909 }
0910 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg2); }
0911 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
0912 BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const noexcept { return arg2; }
0913
0914 template <class T
0915 #ifndef __SUNPRO_CC
0916 ,
0917 typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
0918 #endif
0919 >
0920 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
0921 {
0922 return static_cast<T>(static_cast<result_type>(*this));
0923 }
0924 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
0925 {
0926 result_type r(*this);
0927 return static_cast<bool>(r);
0928 }
0929 template <class T>
0930 BOOST_MP_CXX14_CONSTEXPR T convert_to()
0931 {
0932 result_type r(*this);
0933 return r.template convert_to<T>();
0934 }
0935
0936 static const constexpr unsigned left_depth = left_type::depth + 1;
0937 static const constexpr unsigned right_depth = right_type::depth + 1;
0938 static const constexpr unsigned depth = left_depth > right_depth ? left_depth : right_depth;
0939
0940 private:
0941 typename expression_storage<Arg1>::type arg1;
0942 typename expression_storage<Arg2>::type arg2;
0943 expression& operator=(const expression&);
0944 };
0945
0946 template <class tag, class Arg1, class Arg2, class Arg3>
0947 struct expression<tag, Arg1, Arg2, Arg3, void>
0948 {
0949 using arity = std::integral_constant<int, 3> ;
0950 using left_type = typename arg_type<Arg1>::type ;
0951 using middle_type = typename arg_type<Arg2>::type ;
0952 using right_type = typename arg_type<Arg3>::type ;
0953 using left_result_type = typename left_type::result_type ;
0954 using middle_result_type = typename middle_type::result_type;
0955 using right_result_type = typename right_type::result_type ;
0956 using result_type = typename combine_expression<
0957 left_result_type,
0958 typename combine_expression<right_result_type, middle_result_type>::type>::type;
0959 using tag_type = tag ;
0960
0961 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
0962 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
0963
0964
0965
0966
0967
0968 template <class Other>
0969 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0970 {
0971
0972 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?");
0973 return *this;
0974 }
0975 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0976 {
0977
0978 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?");
0979 return *this;
0980 }
0981 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0982 {
0983
0984 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?");
0985 return *this;
0986 }
0987 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0988 {
0989
0990 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?");
0991 return *this;
0992 }
0993 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0994 {
0995
0996 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?");
0997 return *this;
0998 }
0999 template <class Other>
1000 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1001 {
1002
1003 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?");
1004 return *this;
1005 }
1006 template <class Other>
1007 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1008 {
1009
1010 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?");
1011 return *this;
1012 }
1013 template <class Other>
1014 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1015 {
1016
1017 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?");
1018 return *this;
1019 }
1020 template <class Other>
1021 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1022 {
1023
1024 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?");
1025 return *this;
1026 }
1027 template <class Other>
1028 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1029 {
1030
1031 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?");
1032 return *this;
1033 }
1034 template <class Other>
1035 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1036 {
1037
1038 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?");
1039 return *this;
1040 }
1041 template <class Other>
1042 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1043 {
1044
1045 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?");
1046 return *this;
1047 }
1048 template <class Other>
1049 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1050 {
1051
1052 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?");
1053 return *this;
1054 }
1055 template <class Other>
1056 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1057 {
1058
1059 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?");
1060 return *this;
1061 }
1062 template <class Other>
1063 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1064 {
1065
1066 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?");
1067 return *this;
1068 }
1069
1070 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1071 {
1072 return left_type(arg1);
1073 }
1074 BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
1075 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg3); }
1076 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
1077 BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const noexcept { return arg2; }
1078 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const noexcept { return arg3; }
1079
1080 template <class T
1081 #ifndef __SUNPRO_CC
1082 ,
1083 typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
1084 #endif
1085 >
1086 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1087 {
1088 return static_cast<T>(static_cast<result_type>(*this));
1089 }
1090 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1091 {
1092 result_type r(*this);
1093 return static_cast<bool>(r);
1094 }
1095 template <class T>
1096 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1097 {
1098 result_type r(*this);
1099 return r.template convert_to<T>();
1100 }
1101
1102 static constexpr unsigned left_depth = left_type::depth + 1;
1103 static constexpr unsigned middle_depth = middle_type::depth + 1;
1104 static constexpr unsigned right_depth = right_type::depth + 1;
1105 static constexpr unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
1106
1107 private:
1108 typename expression_storage<Arg1>::type arg1;
1109 typename expression_storage<Arg2>::type arg2;
1110 typename expression_storage<Arg3>::type arg3;
1111 expression& operator=(const expression&);
1112 };
1113
1114 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1115 struct expression
1116 {
1117 using arity = std::integral_constant<int, 4> ;
1118 using left_type = typename arg_type<Arg1>::type ;
1119 using left_middle_type = typename arg_type<Arg2>::type ;
1120 using right_middle_type = typename arg_type<Arg3>::type ;
1121 using right_type = typename arg_type<Arg4>::type ;
1122 using left_result_type = typename left_type::result_type ;
1123 using left_middle_result_type = typename left_middle_type::result_type ;
1124 using right_middle_result_type = typename right_middle_type::result_type;
1125 using right_result_type = typename right_type::result_type ;
1126 using result_type = typename combine_expression<
1127 left_result_type,
1128 typename combine_expression<
1129 left_middle_result_type,
1130 typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type;
1131 using tag_type = tag ;
1132
1133 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) {}
1134 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
1135
1136
1137
1138
1139
1140 template <class Other>
1141 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1142 {
1143
1144 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?");
1145 return *this;
1146 }
1147 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1148 {
1149
1150 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?");
1151 return *this;
1152 }
1153 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1154 {
1155
1156 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?");
1157 return *this;
1158 }
1159 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1160 {
1161
1162 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?");
1163 return *this;
1164 }
1165 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1166 {
1167
1168 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?");
1169 return *this;
1170 }
1171 template <class Other>
1172 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1173 {
1174
1175 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?");
1176 return *this;
1177 }
1178 template <class Other>
1179 BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
1180 {
1181
1182 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?");
1183 return *this;
1184 }
1185 template <class Other>
1186 BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
1187 {
1188
1189 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?");
1190 return *this;
1191 }
1192 template <class Other>
1193 BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
1194 {
1195
1196 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?");
1197 return *this;
1198 }
1199 template <class Other>
1200 BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
1201 {
1202
1203 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?");
1204 return *this;
1205 }
1206 template <class Other>
1207 BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
1208 {
1209
1210 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?");
1211 return *this;
1212 }
1213 template <class Other>
1214 BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
1215 {
1216
1217 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?");
1218 return *this;
1219 }
1220 template <class Other>
1221 BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
1222 {
1223
1224 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?");
1225 return *this;
1226 }
1227 template <class Other>
1228 BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
1229 {
1230
1231 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?");
1232 return *this;
1233 }
1234 template <class Other>
1235 BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
1236 {
1237
1238 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?");
1239 return *this;
1240 }
1241
1242 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1243 {
1244 return left_type(arg1);
1245 }
1246 BOOST_MP_CXX14_CONSTEXPR left_middle_type left_middle() const { return left_middle_type(arg2); }
1247 BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
1248 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg4); }
1249 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
1250 BOOST_MP_CXX14_CONSTEXPR const Arg2& left_middle_ref() const noexcept { return arg2; }
1251 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_middle_ref() const noexcept { return arg3; }
1252 BOOST_MP_CXX14_CONSTEXPR const Arg4& right_ref() const noexcept { return arg4; }
1253
1254 template <class T
1255 #ifndef __SUNPRO_CC
1256 ,
1257 typename std::enable_if<!is_number<T>::value && !std::is_convertible<result_type, T const&>::value && std::is_constructible<T, result_type>::value, int>::type = 0
1258 #endif
1259 >
1260 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1261 {
1262 return static_cast<T>(static_cast<result_type>(*this));
1263 }
1264 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1265 {
1266 result_type r(*this);
1267 return static_cast<bool>(r);
1268 }
1269 template <class T>
1270 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1271 {
1272 result_type r(*this);
1273 return r.template convert_to<T>();
1274 }
1275
1276 static constexpr unsigned left_depth = left_type::depth + 1;
1277 static constexpr unsigned left_middle_depth = left_middle_type::depth + 1;
1278 static constexpr unsigned right_middle_depth = right_middle_type::depth + 1;
1279 static constexpr unsigned right_depth = right_type::depth + 1;
1280
1281 static constexpr unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
1282 static constexpr unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
1283
1284 static constexpr unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
1285
1286 private:
1287 typename expression_storage<Arg1>::type arg1;
1288 typename expression_storage<Arg2>::type arg2;
1289 typename expression_storage<Arg3>::type arg3;
1290 typename expression_storage<Arg4>::type arg4;
1291 expression& operator=(const expression&);
1292 };
1293
1294 template <class T>
1295 struct digits2
1296 {
1297 static_assert(std::numeric_limits<T>::is_specialized, "numeric_limits must be specialized here");
1298 static_assert((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10), "Failed radix check");
1299
1300 static_assert(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1), "Too many digits to cope with here");
1301 static constexpr long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
1302 static inline constexpr long value() noexcept { return m_value; }
1303 };
1304
1305 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
1306 #ifdef _MSC_VER
1307 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1308 #else
1309 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1310 #endif
1311 #endif
1312
1313 template <class S>
1314 void format_float_string(S& str, std::intmax_t my_exp, std::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
1315 {
1316 using size_type = typename S::size_type;
1317
1318 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
1319 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
1320 bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
1321 bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
1322
1323 bool neg = str.size() && (str[0] == '-');
1324
1325 if (neg)
1326 str.erase(0, 1);
1327
1328 if (digits == 0 && !fixed)
1329 {
1330 digits = static_cast<std::intmax_t>((std::max)(str.size(), size_type(16)));
1331 }
1332
1333 if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
1334 {
1335
1336
1337 str = "0";
1338 if (scientific || fixed)
1339 {
1340 if (showpoint || digits > 0) {
1341 str.append(1, '.');
1342 if (digits > 0)
1343 str.append(size_type(digits), '0');
1344 }
1345 if (scientific)
1346 str.append("e+00");
1347 }
1348 else
1349 {
1350 if (showpoint)
1351 {
1352 str.append(1, '.');
1353 if (digits > 1)
1354 str.append(size_type(digits - 1), '0');
1355 }
1356 }
1357 if (neg)
1358 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1359 else if (showpos)
1360 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1361 return;
1362 }
1363
1364 if (!fixed && !scientific && !showpoint)
1365 {
1366
1367
1368
1369 std::string::iterator pos = str.end();
1370 while (pos != str.begin() && *--pos == '0')
1371 {
1372 }
1373 if (pos != str.end())
1374 ++pos;
1375 str.erase(pos, str.end());
1376 if (str.empty())
1377 str = '0';
1378 }
1379 else if (!fixed || (my_exp >= 0))
1380 {
1381
1382
1383
1384 std::intmax_t chars = static_cast<std::intmax_t>(str.size());
1385 chars = digits - chars;
1386 if (scientific)
1387 ++chars;
1388 if (chars > 0)
1389 {
1390 str.append(static_cast<std::string::size_type>(chars), '0');
1391 }
1392 }
1393
1394 if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
1395 {
1396 if (1 + my_exp > static_cast<std::intmax_t>(str.size()))
1397 {
1398
1399 str.append(static_cast<std::string::size_type>(1 + my_exp - static_cast<std::intmax_t>(str.size())), '0');
1400 if (showpoint || (fixed && digits > 0))
1401 str.append(".");
1402 }
1403 else if (my_exp + 1 < static_cast<std::intmax_t>(str.size()))
1404 {
1405 if (my_exp < 0)
1406 {
1407 str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
1408 str.insert(static_cast<std::string::size_type>(0), "0.");
1409 }
1410 else
1411 {
1412
1413 str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
1414 }
1415 }
1416 else if (showpoint || (fixed && digits > 0))
1417 str += ".";
1418
1419 if (fixed)
1420 {
1421
1422 auto pos = str.find('.');
1423 if (pos != str.npos) {
1424 std::intmax_t l = static_cast<std::intmax_t>(pos + 1);
1425 l = static_cast<std::intmax_t>(digits - (static_cast<std::intmax_t>(str.size()) - l));
1426 if (l > 0)
1427 str.append(size_type(l), '0');
1428 }
1429 }
1430 }
1431 else
1432 {
1433 BOOST_MP_USING_ABS
1434
1435 if (showpoint || (str.size() > 1))
1436 str.insert(static_cast<std::string::size_type>(1u), 1, '.');
1437 str.append(static_cast<std::string::size_type>(1u), 'e');
1438
1439 S e;
1440
1441 #ifndef BOOST_MP_STANDALONE
1442 e = boost::lexical_cast<S>(abs(my_exp));
1443 #else
1444 BOOST_IF_CONSTEXPR(std::is_same<S, std::string>::value)
1445 {
1446 e = std::to_string(abs(my_exp));
1447 }
1448 else
1449 {
1450 const std::string str_local_exp = std::to_string(abs(my_exp));
1451 e = S(str_local_exp.cbegin(), str_local_exp.cend());
1452 }
1453 #endif
1454
1455 if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
1456 e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
1457 if (my_exp < 0)
1458 e.insert(static_cast<std::string::size_type>(0), 1, '-');
1459 else
1460 e.insert(static_cast<std::string::size_type>(0), 1, '+');
1461 str.append(e);
1462 }
1463 if (neg)
1464 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1465 else if (showpos)
1466 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1467 }
1468
1469 template <class V>
1470 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&)
1471 {
1472 if (val > (std::numeric_limits<std::size_t>::max)())
1473 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1474 if (val < 0)
1475 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1476 }
1477 template <class V>
1478 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
1479 {
1480 if (val < 0)
1481 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1482 }
1483 template <class V>
1484 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&)
1485 {
1486 if (val > (std::numeric_limits<std::size_t>::max)())
1487 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1488 }
1489 template <class V>
1490 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&) noexcept {}
1491
1492 template <class T>
1493 BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
1494 template <class T>
1495 BOOST_MP_CXX14_CONSTEXPR T&& evaluate_if_expression(T&& val) { return static_cast<T&&>(val); }
1496 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1497 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; }
1498 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1499 BOOST_MP_CXX14_CONSTEXPR typename expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type evaluate_if_expression(expression<tag, Arg1, Arg2, Arg3, Arg4>&& val) { return val; }
1500
1501 template <class T>
1502 struct convertible_to
1503 {
1504 operator T () const;
1505 };
1506
1507 }
1508
1509
1510
1511
1512 enum number_category_type
1513 {
1514 number_kind_unknown = -1,
1515 number_kind_integer = 0,
1516 number_kind_floating_point = 1,
1517 number_kind_rational = 2,
1518 number_kind_fixed_point = 3,
1519 number_kind_complex = 4
1520 };
1521
1522 template <class Num, bool, bool>
1523 struct number_category_base : public std::integral_constant<int, number_kind_unknown>
1524 {};
1525 template <class Num>
1526 struct number_category_base<Num, true, false> : public std::integral_constant<int, std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)>
1527 {};
1528 template <class Num>
1529 struct number_category : public number_category_base<Num, std::is_class<Num>::value || boost::multiprecision::detail::is_arithmetic<Num>::value, std::is_abstract<Num>::value>
1530 {};
1531 template <class Backend, expression_template_option ExpressionTemplates>
1532 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
1533 {};
1534 template <class tag, class A1, class A2, class A3, class A4>
1535 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1536 {};
1537
1538
1539
1540 #ifdef BOOST_HAS_INT128
1541 template <>
1542 struct number_category<boost::multiprecision::int128_type> : public std::integral_constant<int, number_kind_integer>
1543 {};
1544 template <>
1545 struct number_category<boost::multiprecision::uint128_type> : public std::integral_constant<int, number_kind_integer>
1546 {};
1547 #endif
1548 #ifdef BOOST_HAS_FLOAT128
1549 template <>
1550 struct number_category<boost::multiprecision::float128_type> : public std::integral_constant<int, number_kind_floating_point>
1551 {};
1552 #endif
1553
1554 template <class T>
1555 struct component_type
1556 {
1557 using type = T;
1558 };
1559 template <class tag, class A1, class A2, class A3, class A4>
1560 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1561 {};
1562
1563 template <class T>
1564 struct scalar_result_from_possible_complex
1565 {
1566 using type = typename std::conditional<number_category<T>::value == number_kind_complex, typename component_type<T>::type, T>::type;
1567 };
1568
1569 template <class T>
1570 struct complex_result_from_scalar;
1571
1572 template <class T>
1573 struct is_unsigned_number : public std::integral_constant<bool, false>
1574 {};
1575 template <class Backend, expression_template_option ExpressionTemplates>
1576 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
1577 {};
1578 template <class T>
1579 struct is_signed_number : public std::integral_constant<bool, !is_unsigned_number<T>::value>
1580 {};
1581 template <class T>
1582 struct is_interval_number : public std::integral_constant<bool, false>
1583 {};
1584 template <class Backend, expression_template_option ExpressionTemplates>
1585 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
1586 {};
1587
1588 template <class T, class U>
1589 struct is_equivalent_number_type : public std::is_same<T, U>
1590 {};
1591
1592 template <class Backend, expression_template_option ExpressionTemplates, class T2>
1593 struct is_equivalent_number_type<number<Backend, ExpressionTemplates>, T2> : public is_equivalent_number_type<Backend, T2>
1594 {};
1595 template <class T1, class Backend, expression_template_option ExpressionTemplates>
1596 struct is_equivalent_number_type<T1, number<Backend, ExpressionTemplates> > : public is_equivalent_number_type<Backend, T1>
1597 {};
1598 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
1599 struct is_equivalent_number_type<number<Backend, ExpressionTemplates>, number<Backend2, ExpressionTemplates2> > : public is_equivalent_number_type<Backend, Backend2>
1600 {};
1601
1602 }
1603 }
1604
1605 #ifdef BOOST_MP_MATH_AVAILABLE
1606 namespace boost { namespace math {
1607 namespace tools {
1608
1609 template <class T>
1610 struct promote_arg;
1611
1612 template <class tag, class A1, class A2, class A3, class A4>
1613 struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
1614 {
1615 using type = typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
1616 };
1617
1618 template <class R, class B, boost::multiprecision::expression_template_option ET>
1619 inline R real_cast(const boost::multiprecision::number<B, ET>& val)
1620 {
1621 return val.template convert_to<R>();
1622 }
1623
1624 template <class R, class tag, class A1, class A2, class A3, class A4>
1625 inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
1626 {
1627 using val_type = typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
1628 return val_type(val).template convert_to<R>();
1629 }
1630
1631 template <class B, boost::multiprecision::expression_template_option ET>
1632 struct is_complex_type<boost::multiprecision::number<B, ET> > : public std::integral_constant<bool, boost::multiprecision::number_category<B>::value == boost::multiprecision::number_kind_complex> {};
1633
1634 }
1635
1636 namespace constants {
1637
1638 template <class T>
1639 struct is_explicitly_convertible_from_string;
1640
1641 template <class B, boost::multiprecision::expression_template_option ET>
1642 struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
1643 {
1644 static constexpr bool value = true;
1645 };
1646
1647 }
1648
1649 }}
1650 #endif
1651
1652 #ifdef BOOST_MSVC
1653 #pragma warning(pop)
1654 #endif
1655
1656 #endif