File indexing completed on 2025-01-18 09:42:23
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 template <class T, class Num>
0154 struct is_compatible_arithmetic_type
0155 : public std::integral_constant<bool,
0156 std::is_convertible<T, Num>::value && !std::is_same<T, Num>::value && !is_number_expression<T>::value>
0157 {};
0158
0159 namespace detail {
0160
0161
0162
0163 template <class T>
0164 constexpr typename std::enable_if<(boost::multiprecision::detail::is_signed<T>::value || std::is_floating_point<T>::value), T>::type abs(T t) noexcept
0165 {
0166
0167
0168
0169 return t < 0 ? T(1u) + T(-(t + 1)) : t;
0170 }
0171 template <class T>
0172 constexpr typename std::enable_if<boost::multiprecision::detail::is_unsigned<T>::value, T>::type abs(T t) noexcept
0173 {
0174 return t;
0175 }
0176
0177 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
0178
0179 template <class T>
0180 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
0181 {
0182
0183
0184
0185 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);
0186 }
0187 template <class T>
0188 constexpr typename std::enable_if<boost::multiprecision::detail::is_unsigned<T>::value, T>::type unsigned_abs(T t) noexcept
0189 {
0190 return t;
0191 }
0192
0193 template <class T>
0194 struct bits_of
0195 {
0196 static_assert(boost::multiprecision::detail::is_integral<T>::value || std::is_enum<T>::value || std::numeric_limits<T>::is_specialized, "Failed integer size check");
0197 static constexpr unsigned value =
0198 std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
0199 : sizeof(T) * CHAR_BIT - (boost::multiprecision::detail::is_signed<T>::value ? 1 : 0);
0200 };
0201
0202 #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
0203 #define BOOST_MP_BITS_OF_FLOAT128_DEFINED
0204 template <>
0205 struct bits_of<float128_type>
0206 {
0207 static constexpr unsigned value = 113;
0208 };
0209 #endif
0210
0211 template <int b>
0212 struct has_enough_bits
0213 {
0214 template <class T>
0215 struct type : public std::integral_constant<bool, bits_of<T>::value >= b>
0216 {};
0217 };
0218
0219 template <class Tuple, int i, int digits, bool = (i >= std::tuple_size<Tuple>::value)>
0220 struct find_index_of_large_enough_type
0221 {
0222 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;
0223 };
0224 template <class Tuple, int i, int digits>
0225 struct find_index_of_large_enough_type<Tuple, i, digits, true>
0226 {
0227 static constexpr int value = INT_MAX;
0228 };
0229
0230 template <int index, class Tuple, class Fallback, bool = (std::tuple_size<Tuple>::value <= index)>
0231 struct dereference_tuple
0232 {
0233 using type = typename std::tuple_element<static_cast<std::size_t>(index), Tuple>::type;
0234 };
0235 template <int index, class Tuple, class Fallback>
0236 struct dereference_tuple<index, Tuple, Fallback, true>
0237 {
0238 using type = Fallback;
0239 };
0240
0241 template <class Val, class Backend, class Tag>
0242 struct canonical_imp
0243 {
0244 using type = typename std::remove_cv<typename std::decay<const Val>::type>::type;
0245 };
0246 template <class B, class Backend, class Tag>
0247 struct canonical_imp<number<B, et_on>, Backend, Tag>
0248 {
0249 using type = B;
0250 };
0251 template <class B, class Backend, class Tag>
0252 struct canonical_imp<number<B, et_off>, Backend, Tag>
0253 {
0254 using type = B;
0255 };
0256 #ifdef __SUNPRO_CC
0257 template <class B, class Backend>
0258 struct canonical_imp<number<B, et_on>, Backend, std::integral_constant<int, 3> >
0259 {
0260 using type = B;
0261 };
0262 template <class B, class Backend>
0263 struct canonical_imp<number<B, et_off>, Backend, std::integral_constant<int, 3> >
0264 {
0265 using type = B;
0266 };
0267 #endif
0268 template <class Val, class Backend>
0269 struct canonical_imp<Val, Backend, std::integral_constant<int, 0> >
0270 {
0271 static constexpr int index = find_index_of_large_enough_type<typename Backend::signed_types, 0, bits_of<Val>::value>::value;
0272 using type = typename dereference_tuple<index, typename Backend::signed_types, Val>::type;
0273 };
0274 template <class Val, class Backend>
0275 struct canonical_imp<Val, Backend, std::integral_constant<int, 1> >
0276 {
0277 static constexpr int index = find_index_of_large_enough_type<typename Backend::unsigned_types, 0, bits_of<Val>::value>::value;
0278 using type = typename dereference_tuple<index, typename Backend::unsigned_types, Val>::type;
0279 };
0280 template <class Val, class Backend>
0281 struct canonical_imp<Val, Backend, std::integral_constant<int, 2> >
0282 {
0283 static constexpr int index = find_index_of_large_enough_type<typename Backend::float_types, 0, bits_of<Val>::value>::value;
0284 using type = typename dereference_tuple<index, typename Backend::float_types, Val>::type;
0285 };
0286 template <class Val, class Backend>
0287 struct canonical_imp<Val, Backend, std::integral_constant<int, 3> >
0288 {
0289 using type = const char*;
0290 };
0291 template <class Val, class Backend>
0292 struct canonical_imp<Val, Backend, std::integral_constant<int, 4> >
0293 {
0294 using underlying = typename std::underlying_type<Val>::type;
0295 using tag = typename std::conditional<boost::multiprecision::detail::is_signed<Val>::value, std::integral_constant<int, 0>, std::integral_constant<int, 1>>::type;
0296 using type = typename canonical_imp<underlying, Backend, tag>::type;
0297 };
0298
0299 template <class Val, class Backend>
0300 struct canonical
0301 {
0302 using tag_type = typename std::conditional<
0303 boost::multiprecision::detail::is_signed<Val>::value && boost::multiprecision::detail::is_integral<Val>::value,
0304 std::integral_constant<int, 0>,
0305 typename std::conditional<
0306 boost::multiprecision::detail::is_unsigned<Val>::value,
0307 std::integral_constant<int, 1>,
0308 typename std::conditional<
0309 std::is_floating_point<Val>::value,
0310 std::integral_constant<int, 2>,
0311 typename std::conditional<
0312 (std::is_convertible<Val, const char*>::value || std::is_same<Val, std::string>::value),
0313 std::integral_constant<int, 3>,
0314 typename std::conditional<
0315 std::is_enum<Val>::value,
0316 std::integral_constant<int, 4>,
0317 std::integral_constant<int, 5> >::type>::type>::type>::type>::type;
0318
0319 using type = typename canonical_imp<Val, Backend, tag_type>::type;
0320 };
0321
0322 struct terminal
0323 {};
0324 struct negate
0325 {};
0326 struct plus
0327 {};
0328 struct minus
0329 {};
0330 struct multiplies
0331 {};
0332 struct divides
0333 {};
0334 struct modulus
0335 {};
0336 struct shift_left
0337 {};
0338 struct shift_right
0339 {};
0340 struct bitwise_and
0341 {};
0342 struct bitwise_or
0343 {};
0344 struct bitwise_xor
0345 {};
0346 struct bitwise_complement
0347 {};
0348 struct add_immediates
0349 {};
0350 struct subtract_immediates
0351 {};
0352 struct multiply_immediates
0353 {};
0354 struct divide_immediates
0355 {};
0356 struct modulus_immediates
0357 {};
0358 struct bitwise_and_immediates
0359 {};
0360 struct bitwise_or_immediates
0361 {};
0362 struct bitwise_xor_immediates
0363 {};
0364 struct complement_immediates
0365 {};
0366 struct function
0367 {};
0368 struct multiply_add
0369 {};
0370 struct multiply_subtract
0371 {};
0372
0373 template <class T>
0374 struct backend_type;
0375
0376 template <class T, expression_template_option ExpressionTemplates>
0377 struct backend_type<number<T, ExpressionTemplates> >
0378 {
0379 using type = T;
0380 };
0381
0382 template <class tag, class A1, class A2, class A3, class A4>
0383 struct backend_type<expression<tag, A1, A2, A3, A4> >
0384 {
0385 using type = typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type;
0386 };
0387
0388 template <class T1, class T2>
0389 struct combine_expression
0390 {
0391 using type = decltype(T1() + T2());
0392 };
0393
0394 template <class T1, expression_template_option ExpressionTemplates, class T2>
0395 struct combine_expression<number<T1, ExpressionTemplates>, T2>
0396 {
0397 using type = number<T1, ExpressionTemplates>;
0398 };
0399
0400 template <class T1, class T2, expression_template_option ExpressionTemplates>
0401 struct combine_expression<T1, number<T2, ExpressionTemplates> >
0402 {
0403 using type = number<T2, ExpressionTemplates>;
0404 };
0405
0406 template <class T, expression_template_option ExpressionTemplates>
0407 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
0408 {
0409 using type = number<T, ExpressionTemplates>;
0410 };
0411
0412 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
0413 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
0414 {
0415 using type = typename std::conditional<
0416 std::is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
0417 number<T1, ExpressionTemplates1>,
0418 number<T2, ExpressionTemplates2> >::type;
0419 };
0420
0421 template <class T>
0422 struct arg_type
0423 {
0424 using type = expression<terminal, T>;
0425 };
0426
0427 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
0428 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
0429 {
0430 using type = expression<Tag, Arg1, Arg2, Arg3, Arg4>;
0431 };
0432
0433 struct unmentionable
0434 {
0435 unmentionable* proc() { return nullptr; }
0436 };
0437
0438 typedef unmentionable* (unmentionable::*unmentionable_type)();
0439
0440 template <class T, bool b>
0441 struct expression_storage_base
0442 {
0443 using type = const T&;
0444 };
0445
0446 template <class T>
0447 struct expression_storage_base<T, true>
0448 {
0449 using type = T;
0450 };
0451
0452 template <class T>
0453 struct expression_storage : public expression_storage_base<T, boost::multiprecision::detail::is_arithmetic<T>::value>
0454 {};
0455
0456 template <class T>
0457 struct expression_storage<T*>
0458 {
0459 using type = T*;
0460 };
0461
0462 template <class T>
0463 struct expression_storage<const T*>
0464 {
0465 using type = const T*;
0466 };
0467
0468 template <class tag, class A1, class A2, class A3, class A4>
0469 struct expression_storage<expression<tag, A1, A2, A3, A4> >
0470 {
0471 using type = expression<tag, A1, A2, A3, A4>;
0472 };
0473
0474 template <class tag, class Arg1>
0475 struct expression<tag, Arg1, void, void, void>
0476 {
0477 using arity = std::integral_constant<int, 1> ;
0478 using left_type = typename arg_type<Arg1>::type ;
0479 using left_result_type = typename left_type::result_type;
0480 using result_type = typename left_type::result_type;
0481 using tag_type = tag ;
0482
0483 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
0484 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
0485
0486
0487
0488
0489
0490 template <class Other>
0491 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0492 {
0493
0494 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?");
0495 return *this;
0496 }
0497 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0498 {
0499
0500 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?");
0501 return *this;
0502 }
0503 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0504 {
0505
0506 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?");
0507 return *this;
0508 }
0509 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0510 {
0511
0512 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?");
0513 return *this;
0514 }
0515 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0516 {
0517
0518 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?");
0519 return *this;
0520 }
0521 template <class Other>
0522 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
0523 {
0524
0525 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?");
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
0592 BOOST_MP_CXX14_CONSTEXPR left_type left() const
0593 {
0594 return left_type(arg);
0595 }
0596
0597 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg; }
0598
0599 static constexpr unsigned depth = left_type::depth + 1;
0600 template <class T
0601 #ifndef __SUNPRO_CC
0602 ,
0603 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
0604 #endif
0605 >
0606 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
0607 {
0608 return static_cast<T>(static_cast<result_type>(*this));
0609 }
0610 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
0611 {
0612 result_type r(*this);
0613 return static_cast<bool>(r);
0614 }
0615
0616 template <class T>
0617 BOOST_MP_CXX14_CONSTEXPR T convert_to()
0618 {
0619 result_type r(*this);
0620 return r.template convert_to<T>();
0621 }
0622
0623 private:
0624 typename expression_storage<Arg1>::type arg;
0625 expression& operator=(const expression&);
0626 };
0627
0628 template <class Arg1>
0629 struct expression<terminal, Arg1, void, void, void>
0630 {
0631 using arity = std::integral_constant<int, 0>;
0632 using result_type = Arg1 ;
0633 using tag_type = terminal ;
0634
0635 explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
0636 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
0637
0638
0639
0640
0641
0642 template <class Other>
0643 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0644 {
0645
0646 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?");
0647 return *this;
0648 }
0649 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0650 {
0651
0652 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?");
0653 return *this;
0654 }
0655 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0656 {
0657
0658 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?");
0659 return *this;
0660 }
0661 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0662 {
0663
0664 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?");
0665 return *this;
0666 }
0667 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0668 {
0669
0670 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?");
0671 return *this;
0672 }
0673 template <class Other>
0674 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
0675 {
0676
0677 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?");
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
0744 BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const noexcept
0745 {
0746 return arg;
0747 }
0748
0749 static constexpr unsigned depth = 0;
0750
0751 template <class T
0752 #ifndef __SUNPRO_CC
0753 ,
0754 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
0755 #endif
0756 >
0757 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
0758 {
0759 return static_cast<T>(static_cast<result_type>(*this));
0760 }
0761 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
0762 {
0763 result_type r(*this);
0764 return static_cast<bool>(r);
0765 }
0766
0767 template <class T>
0768 BOOST_MP_CXX14_CONSTEXPR T convert_to()
0769 {
0770 result_type r(*this);
0771 return r.template convert_to<T>();
0772 }
0773
0774 private:
0775 typename expression_storage<Arg1>::type arg;
0776 expression& operator=(const expression&);
0777 };
0778
0779 template <class tag, class Arg1, class Arg2>
0780 struct expression<tag, Arg1, Arg2, void, void>
0781 {
0782 using arity = std::integral_constant<int, 2> ;
0783 using left_type = typename arg_type<Arg1>::type ;
0784 using right_type = typename arg_type<Arg2>::type ;
0785 using left_result_type = typename left_type::result_type ;
0786 using right_result_type = typename right_type::result_type ;
0787 using result_type = typename combine_expression<left_result_type, right_result_type>::type;
0788 using tag_type = tag ;
0789
0790 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
0791 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
0792
0793
0794
0795
0796
0797 template <class Other>
0798 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0799 {
0800
0801 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?");
0802 return *this;
0803 }
0804 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0805 {
0806
0807 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?");
0808 return *this;
0809 }
0810 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0811 {
0812
0813 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?");
0814 return *this;
0815 }
0816 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0817 {
0818
0819 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?");
0820 return *this;
0821 }
0822 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0823 {
0824
0825 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?");
0826 return *this;
0827 }
0828 template <class Other>
0829 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
0830 {
0831
0832 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?");
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
0899 BOOST_MP_CXX14_CONSTEXPR left_type left() const
0900 {
0901 return left_type(arg1);
0902 }
0903 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg2); }
0904 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
0905 BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const noexcept { return arg2; }
0906
0907 template <class T
0908 #ifndef __SUNPRO_CC
0909 ,
0910 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
0911 #endif
0912 >
0913 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
0914 {
0915 return static_cast<T>(static_cast<result_type>(*this));
0916 }
0917 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
0918 {
0919 result_type r(*this);
0920 return static_cast<bool>(r);
0921 }
0922 template <class T>
0923 BOOST_MP_CXX14_CONSTEXPR T convert_to()
0924 {
0925 result_type r(*this);
0926 return r.template convert_to<T>();
0927 }
0928
0929 static const constexpr unsigned left_depth = left_type::depth + 1;
0930 static const constexpr unsigned right_depth = right_type::depth + 1;
0931 static const constexpr unsigned depth = left_depth > right_depth ? left_depth : right_depth;
0932
0933 private:
0934 typename expression_storage<Arg1>::type arg1;
0935 typename expression_storage<Arg2>::type arg2;
0936 expression& operator=(const expression&);
0937 };
0938
0939 template <class tag, class Arg1, class Arg2, class Arg3>
0940 struct expression<tag, Arg1, Arg2, Arg3, void>
0941 {
0942 using arity = std::integral_constant<int, 3> ;
0943 using left_type = typename arg_type<Arg1>::type ;
0944 using middle_type = typename arg_type<Arg2>::type ;
0945 using right_type = typename arg_type<Arg3>::type ;
0946 using left_result_type = typename left_type::result_type ;
0947 using middle_result_type = typename middle_type::result_type;
0948 using right_result_type = typename right_type::result_type ;
0949 using result_type = typename combine_expression<
0950 left_result_type,
0951 typename combine_expression<right_result_type, middle_result_type>::type>::type;
0952 using tag_type = tag ;
0953
0954 BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
0955 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
0956
0957
0958
0959
0960
0961 template <class Other>
0962 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
0963 {
0964
0965 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?");
0966 return *this;
0967 }
0968 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
0969 {
0970
0971 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?");
0972 return *this;
0973 }
0974 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
0975 {
0976
0977 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?");
0978 return *this;
0979 }
0980 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
0981 {
0982
0983 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?");
0984 return *this;
0985 }
0986 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
0987 {
0988
0989 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?");
0990 return *this;
0991 }
0992 template <class Other>
0993 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
0994 {
0995
0996 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?");
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
1063 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1064 {
1065 return left_type(arg1);
1066 }
1067 BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
1068 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg3); }
1069 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
1070 BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const noexcept { return arg2; }
1071 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const noexcept { return arg3; }
1072
1073 template <class T
1074 #ifndef __SUNPRO_CC
1075 ,
1076 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
1077 #endif
1078 >
1079 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1080 {
1081 return static_cast<T>(static_cast<result_type>(*this));
1082 }
1083 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1084 {
1085 result_type r(*this);
1086 return static_cast<bool>(r);
1087 }
1088 template <class T>
1089 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1090 {
1091 result_type r(*this);
1092 return r.template convert_to<T>();
1093 }
1094
1095 static constexpr unsigned left_depth = left_type::depth + 1;
1096 static constexpr unsigned middle_depth = middle_type::depth + 1;
1097 static constexpr unsigned right_depth = right_type::depth + 1;
1098 static constexpr unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
1099
1100 private:
1101 typename expression_storage<Arg1>::type arg1;
1102 typename expression_storage<Arg2>::type arg2;
1103 typename expression_storage<Arg3>::type arg3;
1104 expression& operator=(const expression&);
1105 };
1106
1107 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1108 struct expression
1109 {
1110 using arity = std::integral_constant<int, 4> ;
1111 using left_type = typename arg_type<Arg1>::type ;
1112 using left_middle_type = typename arg_type<Arg2>::type ;
1113 using right_middle_type = typename arg_type<Arg3>::type ;
1114 using right_type = typename arg_type<Arg4>::type ;
1115 using left_result_type = typename left_type::result_type ;
1116 using left_middle_result_type = typename left_middle_type::result_type ;
1117 using right_middle_result_type = typename right_middle_type::result_type;
1118 using right_result_type = typename right_type::result_type ;
1119 using result_type = typename combine_expression<
1120 left_result_type,
1121 typename combine_expression<
1122 left_middle_result_type,
1123 typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type;
1124 using tag_type = tag ;
1125
1126 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) {}
1127 BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
1128
1129
1130
1131
1132
1133 template <class Other>
1134 BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
1135 {
1136
1137 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?");
1138 return *this;
1139 }
1140 BOOST_MP_CXX14_CONSTEXPR expression& operator++()
1141 {
1142
1143 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?");
1144 return *this;
1145 }
1146 BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
1147 {
1148
1149 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?");
1150 return *this;
1151 }
1152 BOOST_MP_CXX14_CONSTEXPR expression& operator--()
1153 {
1154
1155 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?");
1156 return *this;
1157 }
1158 BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
1159 {
1160
1161 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?");
1162 return *this;
1163 }
1164 template <class Other>
1165 BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
1166 {
1167
1168 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?");
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
1235 BOOST_MP_CXX14_CONSTEXPR left_type left() const
1236 {
1237 return left_type(arg1);
1238 }
1239 BOOST_MP_CXX14_CONSTEXPR left_middle_type left_middle() const { return left_middle_type(arg2); }
1240 BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
1241 BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg4); }
1242 BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const noexcept { return arg1; }
1243 BOOST_MP_CXX14_CONSTEXPR const Arg2& left_middle_ref() const noexcept { return arg2; }
1244 BOOST_MP_CXX14_CONSTEXPR const Arg3& right_middle_ref() const noexcept { return arg3; }
1245 BOOST_MP_CXX14_CONSTEXPR const Arg4& right_ref() const noexcept { return arg4; }
1246
1247 template <class T
1248 #ifndef __SUNPRO_CC
1249 ,
1250 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
1251 #endif
1252 >
1253 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1254 {
1255 return static_cast<T>(static_cast<result_type>(*this));
1256 }
1257 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1258 {
1259 result_type r(*this);
1260 return static_cast<bool>(r);
1261 }
1262 template <class T>
1263 BOOST_MP_CXX14_CONSTEXPR T convert_to()
1264 {
1265 result_type r(*this);
1266 return r.template convert_to<T>();
1267 }
1268
1269 static constexpr unsigned left_depth = left_type::depth + 1;
1270 static constexpr unsigned left_middle_depth = left_middle_type::depth + 1;
1271 static constexpr unsigned right_middle_depth = right_middle_type::depth + 1;
1272 static constexpr unsigned right_depth = right_type::depth + 1;
1273
1274 static constexpr unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
1275 static constexpr unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
1276
1277 static constexpr unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
1278
1279 private:
1280 typename expression_storage<Arg1>::type arg1;
1281 typename expression_storage<Arg2>::type arg2;
1282 typename expression_storage<Arg3>::type arg3;
1283 typename expression_storage<Arg4>::type arg4;
1284 expression& operator=(const expression&);
1285 };
1286
1287 template <class T>
1288 struct digits2
1289 {
1290 static_assert(std::numeric_limits<T>::is_specialized, "numeric_limits must be specialized here");
1291 static_assert((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10), "Failed radix check");
1292
1293 static_assert(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1), "Too many digits to cope with here");
1294 static constexpr long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
1295 static inline constexpr long value() noexcept { return m_value; }
1296 };
1297
1298 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
1299 #ifdef _MSC_VER
1300 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1301 #else
1302 #define BOOST_MP_MIN_EXPONENT_DIGITS 2
1303 #endif
1304 #endif
1305
1306 template <class S>
1307 void format_float_string(S& str, std::intmax_t my_exp, std::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
1308 {
1309 using size_type = typename S::size_type;
1310
1311 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
1312 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
1313 bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
1314 bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
1315
1316 bool neg = str.size() && (str[0] == '-');
1317
1318 if (neg)
1319 str.erase(0, 1);
1320
1321 if (digits == 0 && !fixed)
1322 {
1323 digits = static_cast<std::intmax_t>((std::max)(str.size(), size_type(16)));
1324 }
1325
1326 if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
1327 {
1328
1329
1330 str = "0";
1331 if (scientific || fixed)
1332 {
1333 if (showpoint || digits > 0) {
1334 str.append(1, '.');
1335 if (digits > 0)
1336 str.append(size_type(digits), '0');
1337 }
1338 if (scientific)
1339 str.append("e+00");
1340 }
1341 else
1342 {
1343 if (showpoint)
1344 {
1345 str.append(1, '.');
1346 if (digits > 1)
1347 str.append(size_type(digits - 1), '0');
1348 }
1349 }
1350 if (neg)
1351 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1352 else if (showpos)
1353 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1354 return;
1355 }
1356
1357 if (!fixed && !scientific && !showpoint)
1358 {
1359
1360
1361
1362 std::string::iterator pos = str.end();
1363 while (pos != str.begin() && *--pos == '0')
1364 {
1365 }
1366 if (pos != str.end())
1367 ++pos;
1368 str.erase(pos, str.end());
1369 if (str.empty())
1370 str = '0';
1371 }
1372 else if (!fixed || (my_exp >= 0))
1373 {
1374
1375
1376
1377 std::intmax_t chars = static_cast<std::intmax_t>(str.size());
1378 chars = digits - chars;
1379 if (scientific)
1380 ++chars;
1381 if (chars > 0)
1382 {
1383 str.append(static_cast<std::string::size_type>(chars), '0');
1384 }
1385 }
1386
1387 if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
1388 {
1389 if (1 + my_exp > static_cast<std::intmax_t>(str.size()))
1390 {
1391
1392 str.append(static_cast<std::string::size_type>(1 + my_exp - static_cast<std::intmax_t>(str.size())), '0');
1393 if (showpoint || (fixed && digits > 0))
1394 str.append(".");
1395 }
1396 else if (my_exp + 1 < static_cast<std::intmax_t>(str.size()))
1397 {
1398 if (my_exp < 0)
1399 {
1400 str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
1401 str.insert(static_cast<std::string::size_type>(0), "0.");
1402 }
1403 else
1404 {
1405
1406 str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
1407 }
1408 }
1409 else if (showpoint || (fixed && digits > 0))
1410 str += ".";
1411
1412 if (fixed)
1413 {
1414
1415 auto pos = str.find('.');
1416 if (pos != str.npos) {
1417 std::intmax_t l = static_cast<std::intmax_t>(pos + 1);
1418 l = static_cast<std::intmax_t>(digits - (static_cast<std::intmax_t>(str.size()) - l));
1419 if (l > 0)
1420 str.append(size_type(l), '0');
1421 }
1422 }
1423 }
1424 else
1425 {
1426 BOOST_MP_USING_ABS
1427
1428 if (showpoint || (str.size() > 1))
1429 str.insert(static_cast<std::string::size_type>(1u), 1, '.');
1430 str.append(static_cast<std::string::size_type>(1u), 'e');
1431
1432 S e;
1433
1434 #ifndef BOOST_MP_STANDALONE
1435 e = boost::lexical_cast<S>(abs(my_exp));
1436 #else
1437 BOOST_IF_CONSTEXPR(std::is_same<S, std::string>::value)
1438 {
1439 e = std::to_string(abs(my_exp));
1440 }
1441 else
1442 {
1443 const std::string str_local_exp = std::to_string(abs(my_exp));
1444 e = S(str_local_exp.cbegin(), str_local_exp.cend());
1445 }
1446 #endif
1447
1448 if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
1449 e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
1450 if (my_exp < 0)
1451 e.insert(static_cast<std::string::size_type>(0), 1, '-');
1452 else
1453 e.insert(static_cast<std::string::size_type>(0), 1, '+');
1454 str.append(e);
1455 }
1456 if (neg)
1457 str.insert(static_cast<std::string::size_type>(0), 1, '-');
1458 else if (showpos)
1459 str.insert(static_cast<std::string::size_type>(0), 1, '+');
1460 }
1461
1462 template <class V>
1463 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&)
1464 {
1465 if (val > (std::numeric_limits<std::size_t>::max)())
1466 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1467 if (val < 0)
1468 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1469 }
1470 template <class V>
1471 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
1472 {
1473 if (val < 0)
1474 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
1475 }
1476 template <class V>
1477 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&)
1478 {
1479 if (val > (std::numeric_limits<std::size_t>::max)())
1480 BOOST_MP_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
1481 }
1482 template <class V>
1483 BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&) noexcept {}
1484
1485 template <class T>
1486 BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
1487 template <class T>
1488 BOOST_MP_CXX14_CONSTEXPR T&& evaluate_if_expression(T&& val) { return static_cast<T&&>(val); }
1489 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1490 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; }
1491 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1492 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; }
1493
1494 template <class T>
1495 struct convertible_to
1496 {
1497 operator T () const;
1498 };
1499
1500 }
1501
1502
1503
1504
1505 enum number_category_type
1506 {
1507 number_kind_unknown = -1,
1508 number_kind_integer = 0,
1509 number_kind_floating_point = 1,
1510 number_kind_rational = 2,
1511 number_kind_fixed_point = 3,
1512 number_kind_complex = 4
1513 };
1514
1515 template <class Num, bool, bool>
1516 struct number_category_base : public std::integral_constant<int, number_kind_unknown>
1517 {};
1518 template <class Num>
1519 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)>
1520 {};
1521 template <class Num>
1522 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>
1523 {};
1524 template <class Backend, expression_template_option ExpressionTemplates>
1525 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
1526 {};
1527 template <class tag, class A1, class A2, class A3, class A4>
1528 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1529 {};
1530
1531
1532
1533 #ifdef BOOST_HAS_INT128
1534 template <>
1535 struct number_category<boost::multiprecision::int128_type> : public std::integral_constant<int, number_kind_integer>
1536 {};
1537 template <>
1538 struct number_category<boost::multiprecision::uint128_type> : public std::integral_constant<int, number_kind_integer>
1539 {};
1540 #endif
1541 #ifdef BOOST_HAS_FLOAT128
1542 template <>
1543 struct number_category<boost::multiprecision::float128_type> : public std::integral_constant<int, number_kind_floating_point>
1544 {};
1545 #endif
1546
1547 template <class T>
1548 struct component_type
1549 {
1550 using type = T;
1551 };
1552 template <class tag, class A1, class A2, class A3, class A4>
1553 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
1554 {};
1555
1556 template <class T>
1557 struct scalar_result_from_possible_complex
1558 {
1559 using type = typename std::conditional<number_category<T>::value == number_kind_complex, typename component_type<T>::type, T>::type;
1560 };
1561
1562 template <class T>
1563 struct complex_result_from_scalar;
1564
1565 template <class T>
1566 struct is_unsigned_number : public std::integral_constant<bool, false>
1567 {};
1568 template <class Backend, expression_template_option ExpressionTemplates>
1569 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
1570 {};
1571 template <class T>
1572 struct is_signed_number : public std::integral_constant<bool, !is_unsigned_number<T>::value>
1573 {};
1574 template <class T>
1575 struct is_interval_number : public std::integral_constant<bool, false>
1576 {};
1577 template <class Backend, expression_template_option ExpressionTemplates>
1578 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
1579 {};
1580
1581 template <class T, class U>
1582 struct is_equivalent_number_type : public std::is_same<T, U>
1583 {};
1584
1585 template <class Backend, expression_template_option ExpressionTemplates, class T2>
1586 struct is_equivalent_number_type<number<Backend, ExpressionTemplates>, T2> : public is_equivalent_number_type<Backend, T2>
1587 {};
1588 template <class T1, class Backend, expression_template_option ExpressionTemplates>
1589 struct is_equivalent_number_type<T1, number<Backend, ExpressionTemplates> > : public is_equivalent_number_type<Backend, T1>
1590 {};
1591 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
1592 struct is_equivalent_number_type<number<Backend, ExpressionTemplates>, number<Backend2, ExpressionTemplates2> > : public is_equivalent_number_type<Backend, Backend2>
1593 {};
1594
1595 }
1596 }
1597
1598 #ifdef BOOST_MP_MATH_AVAILABLE
1599 namespace boost { namespace math {
1600 namespace tools {
1601
1602 template <class T>
1603 struct promote_arg;
1604
1605 template <class tag, class A1, class A2, class A3, class A4>
1606 struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
1607 {
1608 using type = typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
1609 };
1610
1611 template <class R, class B, boost::multiprecision::expression_template_option ET>
1612 inline R real_cast(const boost::multiprecision::number<B, ET>& val)
1613 {
1614 return val.template convert_to<R>();
1615 }
1616
1617 template <class R, class tag, class A1, class A2, class A3, class A4>
1618 inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
1619 {
1620 using val_type = typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
1621 return val_type(val).template convert_to<R>();
1622 }
1623
1624 template <class B, boost::multiprecision::expression_template_option ET>
1625 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> {};
1626
1627 }
1628
1629 namespace constants {
1630
1631 template <class T>
1632 struct is_explicitly_convertible_from_string;
1633
1634 template <class B, boost::multiprecision::expression_template_option ET>
1635 struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
1636 {
1637 static constexpr bool value = true;
1638 };
1639
1640 }
1641
1642 }}
1643 #endif
1644
1645 #ifdef BOOST_MSVC
1646 #pragma warning(pop)
1647 #endif
1648
1649 #endif