File indexing completed on 2025-12-16 09:58:17
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MP_NUMBER_HPP
0007 #define BOOST_MP_NUMBER_HPP
0008
0009 #include <cstdint>
0010 #include <boost/multiprecision/detail/standalone_config.hpp>
0011 #include <boost/multiprecision/detail/precision.hpp>
0012 #include <boost/multiprecision/detail/generic_interconvert.hpp>
0013 #include <boost/multiprecision/detail/number_compare.hpp>
0014 #include <boost/multiprecision/traits/is_restricted_conversion.hpp>
0015 #include <boost/multiprecision/traits/is_complex.hpp>
0016 #include <boost/multiprecision/traits/is_convertible_arithmetic.hpp>
0017 #include <boost/multiprecision/detail/hash.hpp>
0018 #include <boost/multiprecision/detail/number_base.hpp>
0019 #include <istream> // stream operators
0020 #include <cstdio> // EOF
0021 #include <cctype> // isspace
0022 #include <functional> // std::hash
0023 #include <type_traits>
0024 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
0025 #include <string_view>
0026 #endif
0027
0028 #ifndef BOOST_MP_STANDALONE
0029 #include <boost/core/nvp.hpp>
0030 #endif
0031
0032 namespace boost {
0033 namespace multiprecision {
0034
0035 #ifdef BOOST_MSVC
0036
0037
0038 #pragma warning(push)
0039 #pragma warning(disable : 4127 4714 6326)
0040 #endif
0041
0042 template <class Backend, expression_template_option ExpressionTemplates>
0043 class number
0044 {
0045 using self_type = number<Backend, ExpressionTemplates>;
0046
0047 public:
0048 using backend_type = Backend ;
0049 using value_type = typename component_type<self_type>::type;
0050
0051 static constexpr expression_template_option et = ExpressionTemplates;
0052
0053 BOOST_MP_FORCEINLINE constexpr number() noexcept(noexcept(Backend())) {}
0054 BOOST_MP_FORCEINLINE constexpr number(const number& e) noexcept(noexcept(Backend(std::declval<Backend const&>()))) = default;
0055 template <class V>
0056 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v,
0057 typename std::enable_if<
0058 (boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
0059 || std::is_same<std::string, V>::value
0060 || std::is_convertible<V, const char*>::value)
0061 && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
0062 && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
0063 {
0064 m_backend = canonical_value(v);
0065 }
0066 template <class V>
0067 BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
0068 std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
0069 #ifndef BOOST_INTEL
0070 noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
0071 #endif
0072 : m_backend(canonical_value(v))
0073 {}
0074 template <class V, class U>
0075 BOOST_MP_FORCEINLINE constexpr number(const V& v, U digits10,
0076 typename std::enable_if<
0077 (boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
0078 || std::is_same<std::string, V>::value
0079 || std::is_convertible<V, const char*>::value)
0080 && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
0081 && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex)
0082 && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)
0083 && std::is_same<self_type, value_type>::value
0084 && std::is_integral<U>::value
0085 && (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)
0086 && std::is_constructible<Backend, typename detail::canonical<V, Backend>::type const&, unsigned>::value>::type* = nullptr)
0087 : m_backend(canonical_value(v), static_cast<unsigned>(digits10))
0088 {}
0089
0090
0091
0092 template <class V>
0093 BOOST_MP_FORCEINLINE
0094 #if !(defined(BOOST_MSVC) && (BOOST_MSVC <= 1900))
0095 constexpr
0096 #endif
0097 number(const V& v, typename std::enable_if<
0098 std::is_enum<V>::value && std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
0099 : number(static_cast<typename std::underlying_type<V>::type>(v))
0100 {}
0101
0102
0103
0104 template <class V>
0105 BOOST_MP_FORCEINLINE explicit
0106 #if !(defined(BOOST_MSVC) && (BOOST_MSVC <= 1900))
0107 constexpr
0108 #endif
0109 number(const V& v, typename std::enable_if<
0110 std::is_enum<V>::value && !std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
0111 : number(static_cast<typename std::underlying_type<V>::type>(v))
0112 {}
0113
0114 template <class U>
0115 BOOST_MP_FORCEINLINE constexpr number(const number& e, U digits10, typename std::enable_if<std::is_constructible<Backend, const Backend&, unsigned>::value && std::is_integral<U>::value && (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)>::type* = nullptr)
0116 noexcept(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))
0117 : m_backend(e.m_backend, static_cast<unsigned>(digits10)) {}
0118 template <class V>
0119 explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename std::enable_if<
0120 (boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
0121 noexcept(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
0122 {
0123 m_backend = canonical_value(v);
0124 }
0125 template <class V>
0126 explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
0127 detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value || !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)>::type* = nullptr)
0128 noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
0129 : m_backend(canonical_value(v)) {}
0130 template <class V>
0131 explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)>::type* = nullptr)
0132 : m_backend(canonical_value(v), digits10) {}
0133
0134 template <expression_template_option ET>
0135 BOOST_MP_FORCEINLINE constexpr number(const number<Backend, ET>& val)
0136 noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(val.backend()) {}
0137
0138 template <class Other, expression_template_option ET>
0139 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val,
0140 typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
0141 noexcept(noexcept(Backend(std::declval<Other const&>())))
0142 : m_backend(val.backend()) {}
0143
0144 template <class Other, expression_template_option ET>
0145 explicit BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
0146 (!detail::is_explicitly_convertible<Other, Backend>::value)>::type* = nullptr)
0147 {
0148
0149
0150
0151 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard_1(val);
0152 detail::scoped_default_precision<number<Other, ET> > precision_guard_2(val);
0153 using detail::generic_interconvert;
0154 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0155 {
0156 if (precision_guard_1.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0157 {
0158 self_type t;
0159 generic_interconvert(t.backend(), val.backend(), number_category<Backend>(), number_category<Other>());
0160 *this = std::move(t);
0161 return;
0162 }
0163 }
0164 generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
0165 }
0166 template <class Other, expression_template_option ET>
0167 explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
0168 (detail::is_explicitly_convertible<Other, Backend>::value && (detail::is_restricted_conversion<Other, Backend>::value || !std::is_convertible<Other, Backend>::value))>::type* = nullptr) noexcept(noexcept(Backend(std::declval<Other const&>())))
0169 : m_backend(val.backend()) {}
0170
0171 template <class V, class U>
0172 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
0173 typename std::enable_if<
0174 (std::is_convertible<V, value_type>::value
0175 && std::is_convertible<U, value_type>::value
0176 && !std::is_same<value_type, self_type>::value
0177 && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
0178 && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
0179 : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)))
0180 {
0181 }
0182 template <class V, class U>
0183 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, const U& v2,
0184 typename std::enable_if<
0185 (std::is_convertible<V, value_type>::value
0186 && std::is_convertible<U, value_type>::value
0187 && !std::is_same<value_type, self_type>::value
0188 && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
0189 && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
0190 : m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(v2)))
0191 {
0192 }
0193 template <class V, class U>
0194 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, U&& v2,
0195 typename std::enable_if<
0196 (std::is_convertible<V, value_type>::value
0197 && std::is_convertible<U, value_type>::value
0198 && !std::is_same<value_type, self_type>::value
0199 && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
0200 && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
0201 : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
0202 {
0203 }
0204 template <class V, class U>
0205 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, U&& v2,
0206 typename std::enable_if<
0207 (std::is_convertible<V, value_type>::value
0208 && std::is_convertible<U, value_type>::value
0209 && !std::is_same<value_type, self_type>::value
0210 && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
0211 && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
0212 : m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
0213 {
0214 }
0215 template <class V, class U>
0216 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
0217 typename std::enable_if<
0218 (std::is_convertible<V, value_type>::value
0219 && std::is_convertible<U, value_type>::value
0220 && !std::is_same<value_type, self_type>::value
0221 && (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
0222 || boost::multiprecision::detail::is_variable_precision<Backend>::value))>::type* = nullptr)
0223 {
0224 using default_ops::assign_components;
0225
0226 boost::multiprecision::detail::scoped_precision_options<value_type> scoped_opts(*this);
0227
0228 detail::scoped_default_precision<self_type> precision_guard(v1, v2, *this);
0229 detail::scoped_default_precision<value_type> component_precision_guard(v1, v2, *this);
0230 assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
0231 }
0232 template <class V, class U>
0233 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
0234 typename std::enable_if<
0235 (std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value && !std::is_same<V, self_type>::value && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
0236 {
0237 using default_ops::assign_components;
0238
0239 boost::multiprecision::detail::scoped_precision_options<value_type> scoped_opts(*this);
0240
0241 detail::scoped_default_precision<self_type> precision_guard(v1, v2, *this);
0242 detail::scoped_default_precision<value_type> component_precision_guard(v1, v2, *this);
0243 assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
0244 }
0245 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
0246
0247
0248
0249 template <class Traits>
0250 explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view)
0251 {
0252 using default_ops::assign_from_string_view;
0253 assign_from_string_view(this->backend(), view);
0254 }
0255 template <class Traits>
0256 explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
0257 {
0258 using default_ops::assign_from_string_view;
0259 assign_from_string_view(this->backend(), view_x, view_y);
0260 }
0261 template <class Traits>
0262 explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& v, unsigned digits10)
0263 : m_backend(canonical_value(v), digits10) {}
0264 template <class Traits>
0265 BOOST_MP_CXX14_CONSTEXPR number& assign(const std::basic_string_view<char, Traits>& view)
0266 {
0267 using default_ops::assign_from_string_view;
0268 assign_from_string_view(this->backend(), view);
0269 return *this;
0270 }
0271 #endif
0272
0273 template <class V, class U>
0274 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
0275 typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value)>::type* = nullptr)
0276 : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10)
0277 {}
0278 template <class V, class U>
0279 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
0280 typename std::enable_if<((std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value) && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
0281 : m_backend(detail::evaluate_if_expression(v1), detail::evaluate_if_expression(v2), digits10) {}
0282
0283 template <class Other, expression_template_option ET>
0284 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(
0285 const number<Other, ET>& v1,
0286 const number<Other, ET>& v2,
0287 typename std::enable_if<
0288 std::is_convertible<Other, Backend>::value
0289 && (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&>::value || boost::multiprecision::detail::is_variable_precision<Backend>::value) >::type* = nullptr)
0290 {
0291 using default_ops::assign_components;
0292 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
0293 assign_components(m_backend, v1.backend(), v2.backend());
0294 }
0295
0296 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0297 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0298 {
0299 using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
0300 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310 BOOST_IF_CONSTEXPR (std::is_same<self_type, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
0311 {
0312 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0313 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0314 {
0315 number t(e);
0316 return *this = std::move(t);
0317 }
0318 }
0319 do_assign(e, tag_type());
0320 return *this;
0321 }
0322 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0323 BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0324 {
0325 using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336 BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
0337 {
0338 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0339 {
0340 const detail::scoped_default_precision<number<Backend, ExpressionTemplates>> precision_guard(e);
0341
0342 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0343 {
0344 number t;
0345 t.assign(e);
0346 return *this = std::move(t);
0347 }
0348 }
0349 }
0350 do_assign(e, tag_type());
0351 return *this;
0352 }
0353 BOOST_MP_CXX14_CONSTEXPR number& assign(const value_type& a, const value_type& b)
0354 {
0355 assign_components(backend(), a.backend(), b.backend());
0356 return *this;
0357 }
0358 template <class V, class U>
0359 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(std::is_convertible<V, value_type>::value&& std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value), number&>::type
0360 assign(const V& v1, const U& v2, unsigned Digits)
0361 {
0362 self_type r(v1, v2, Digits);
0363 boost::multiprecision::detail::scoped_source_precision<self_type> scope;
0364 return *this = r;
0365 }
0366 BOOST_MP_CXX14_CONSTEXPR number& assign(const value_type & a, const value_type & b, unsigned Digits)
0367 {
0368 this->precision(Digits);
0369 boost::multiprecision::detail::scoped_target_precision<self_type> scoped;
0370 assign_components(backend(), canonical_value(detail::evaluate_if_expression(a)), canonical_value(detail::evaluate_if_expression(b)));
0371 return *this;
0372 }
0373
0374 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(const number& e)
0375 noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend const&>())) = default;
0376
0377 template <class V>
0378 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0379 operator=(const V& v)
0380 noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
0381 {
0382 m_backend = canonical_value(v);
0383 return *this;
0384 }
0385 template <class V>
0386 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v)
0387 noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
0388 {
0389 m_backend = canonical_value(v);
0390 return *this;
0391 }
0392 template <class V, class U>
0393 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v, const U& digits10_or_component)
0394 noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
0395 {
0396 number t(v, digits10_or_component);
0397 boost::multiprecision::detail::scoped_source_precision<self_type> scope;
0398 static_cast<void>(scope);
0399 return *this = t;
0400 }
0401 template <class Other, expression_template_option ET>
0402 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>::value, number<Backend, ExpressionTemplates>&>::type
0403 assign(const number<Other, ET>& v)
0404 {
0405
0406
0407
0408 using detail::generic_interconvert;
0409 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
0410 detail::scoped_default_precision<number<Other, ET> > precision_guard2(*this, v);
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0421 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0422 {
0423 number t(v);
0424 return *this = std::move(t);
0425 }
0426 generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
0427 return *this;
0428 }
0429
0430 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0431 BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
0432 {
0433
0434
0435
0436 *this = e;
0437 }
0438 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0439 explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
0440 typename std::enable_if<!std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
0441 {
0442
0443
0444
0445 assign(e);
0446 }
0447
0448
0449 BOOST_MP_FORCEINLINE constexpr number(number&& r)
0450 noexcept(noexcept(Backend(std::declval<Backend>()))) = default;
0451 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(number&& r) noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend>())) = default;
0452
0453 template <class Other, expression_template_option ET>
0454 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(number<Other, ET>&& val,
0455 typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
0456 noexcept(noexcept(Backend(std::declval<Other const&>())))
0457 : m_backend(static_cast<number<Other, ET>&&>(val).backend()) {}
0458 template <class Other, expression_template_option ET>
0459 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value), number&>::type
0460 operator=(number<Other, ET>&& val)
0461 noexcept(noexcept(Backend(std::declval<Other const&>())))
0462 {
0463 m_backend = std::move(val).backend();
0464 return *this;
0465 }
0466
0467 BOOST_MP_CXX14_CONSTEXPR number& operator+=(const self_type& val)
0468 {
0469 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0480 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0481 {
0482 number t(*this + val);
0483 return *this = std::move(t);
0484 }
0485 do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
0486 return *this;
0487 }
0488
0489 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0490 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0491 {
0492 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0493
0494
0495 if ((contains_self(e) && !is_self(e)))
0496 {
0497 self_type temp(e);
0498 do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0499 }
0500 else
0501 {
0502 do_add(e, tag());
0503 }
0504 return *this;
0505 }
0506
0507 template <class Arg1, class Arg2, class Arg3, class Arg4>
0508 BOOST_MP_CXX14_CONSTEXPR number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
0509 {
0510 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520 BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
0521 {
0522 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0523 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0524 {
0525 number t(*this + e);
0526 return *this = std::move(t);
0527 }
0528 }
0529
0530
0531
0532 using default_ops::eval_multiply_add;
0533 eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
0534 return *this;
0535 }
0536
0537 template <class V>
0538 typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0539 BOOST_MP_CXX14_CONSTEXPR operator+=(const V& v)
0540 {
0541 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0552 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0553 {
0554 number t(*this + v);
0555 return *this = std::move(t);
0556 }
0557
0558 using default_ops::eval_add;
0559 eval_add(m_backend, canonical_value(v));
0560 return *this;
0561 }
0562
0563 BOOST_MP_CXX14_CONSTEXPR number& operator-=(const self_type& val)
0564 {
0565 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0576 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0577 {
0578 number t(*this - val);
0579 return *this = std::move(t);
0580 }
0581 do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
0582 return *this;
0583 }
0584
0585 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0586 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0587 {
0588 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0589
0590 if (contains_self(e))
0591 {
0592 self_type temp(e);
0593 do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0594 }
0595 else
0596 {
0597 do_subtract(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
0598 }
0599 return *this;
0600 }
0601
0602 template <class V>
0603 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0604 operator-=(const V& v)
0605 {
0606 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0617 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0618 {
0619 number t(*this - v);
0620 return *this = std::move(t);
0621 }
0622
0623 using default_ops::eval_subtract;
0624 eval_subtract(m_backend, canonical_value(v));
0625 return *this;
0626 }
0627
0628 template <class Arg1, class Arg2, class Arg3, class Arg4>
0629 BOOST_MP_CXX14_CONSTEXPR number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
0630 {
0631 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641 BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
0642 {
0643 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0644 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0645 {
0646 number t(*this - e);
0647 return *this = std::move(t);
0648 }
0649 }
0650
0651
0652
0653 using default_ops::eval_multiply_subtract;
0654 eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
0655 return *this;
0656 }
0657
0658 BOOST_MP_CXX14_CONSTEXPR number& operator*=(const self_type& e)
0659 {
0660 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0671 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0672 {
0673 number t(*this * e);
0674 return *this = std::move(t);
0675 }
0676 do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
0677 return *this;
0678 }
0679
0680 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0681 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0682 {
0683 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0684
0685
0686 if ((contains_self(e) && !is_self(e)))
0687 {
0688 self_type temp(e);
0689 do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0690 }
0691 else
0692 {
0693 do_multiplies(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
0694 }
0695 return *this;
0696 }
0697
0698 template <class V>
0699 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0700 operator*=(const V& v)
0701 {
0702 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0713 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0714 {
0715 number t(*this * v);
0716 return *this = std::move(t);
0717 }
0718
0719 using default_ops::eval_multiply;
0720 eval_multiply(m_backend, canonical_value(v));
0721 return *this;
0722 }
0723
0724 BOOST_MP_CXX14_CONSTEXPR number& operator%=(const self_type& e)
0725 {
0726 static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
0727 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0738 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0739 {
0740 number t(*this % e);
0741 return *this = std::move(t);
0742 }
0743 do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());
0744 return *this;
0745 }
0746 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0747 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0748 {
0749 static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
0750 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0751
0752 if (contains_self(e))
0753 {
0754 self_type temp(e);
0755 do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0756 }
0757 else
0758 {
0759 do_modulus(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
0760 }
0761 return *this;
0762 }
0763 template <class V>
0764 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0765 operator%=(const V& v)
0766 {
0767 static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
0768 using default_ops::eval_modulus;
0769 eval_modulus(m_backend, canonical_value(v));
0770 return *this;
0771 }
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator++()
0782 {
0783 using default_ops::eval_increment;
0784 eval_increment(m_backend);
0785 return *this;
0786 }
0787
0788 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator--()
0789 {
0790 using default_ops::eval_decrement;
0791 eval_decrement(m_backend);
0792 return *this;
0793 }
0794
0795 inline BOOST_MP_CXX14_CONSTEXPR number operator++(int)
0796 {
0797 using default_ops::eval_increment;
0798 self_type temp(*this);
0799 eval_increment(m_backend);
0800 return temp;
0801 }
0802
0803 inline BOOST_MP_CXX14_CONSTEXPR number operator--(int)
0804 {
0805 using default_ops::eval_decrement;
0806 self_type temp(*this);
0807 eval_decrement(m_backend);
0808 return temp;
0809 }
0810
0811 template <class V>
0812 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator<<=(V val)
0813 {
0814 static_assert(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");
0815 detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value > ());
0816 eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
0817 return *this;
0818 }
0819
0820 template <class V>
0821 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator>>=(V val)
0822 {
0823 static_assert(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");
0824 detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value>());
0825 eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
0826 return *this;
0827 }
0828
0829 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator/=(const self_type& e)
0830 {
0831 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0842 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0843 {
0844 number t(*this / e);
0845 return *this = std::move(t);
0846 }
0847 do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
0848 return *this;
0849 }
0850
0851 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0852 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0853 {
0854 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
0855
0856 if (contains_self(e))
0857 {
0858 self_type temp(e);
0859 do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0860 }
0861 else
0862 {
0863 do_divide(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
0864 }
0865 return *this;
0866 }
0867
0868 template <class V>
0869 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0870 operator/=(const V& v)
0871 {
0872 detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, v);
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882 BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
0883 if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
0884 {
0885 number t(*this / v);
0886 return *this = std::move(t);
0887 }
0888
0889 using default_ops::eval_divide;
0890 eval_divide(m_backend, canonical_value(v));
0891 return *this;
0892 }
0893
0894 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator&=(const self_type& e)
0895 {
0896 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
0897 do_bitwise_and(detail::expression<detail::terminal, self_type>(e), detail::terminal());
0898 return *this;
0899 }
0900
0901 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0902 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0903 {
0904 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
0905
0906
0907 if (contains_self(e) && !is_self(e))
0908 {
0909 self_type temp(e);
0910 do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0911 }
0912 else
0913 {
0914 do_bitwise_and(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
0915 }
0916 return *this;
0917 }
0918
0919 template <class V>
0920 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0921 operator&=(const V& v)
0922 {
0923 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
0924 using default_ops::eval_bitwise_and;
0925 eval_bitwise_and(m_backend, canonical_value(v));
0926 return *this;
0927 }
0928
0929 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator|=(const self_type& e)
0930 {
0931 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
0932 do_bitwise_or(detail::expression<detail::terminal, self_type>(e), detail::terminal());
0933 return *this;
0934 }
0935
0936 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0937 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0938 {
0939 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
0940
0941
0942 if (contains_self(e) && !is_self(e))
0943 {
0944 self_type temp(e);
0945 do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0946 }
0947 else
0948 {
0949 do_bitwise_or(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
0950 }
0951 return *this;
0952 }
0953
0954 template <class V>
0955 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0956 operator|=(const V& v)
0957 {
0958 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
0959 using default_ops::eval_bitwise_or;
0960 eval_bitwise_or(m_backend, canonical_value(v));
0961 return *this;
0962 }
0963
0964 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator^=(const self_type& e)
0965 {
0966 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
0967 do_bitwise_xor(detail::expression<detail::terminal, self_type>(e), detail::terminal());
0968 return *this;
0969 }
0970
0971 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0972 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
0973 {
0974 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
0975 if (contains_self(e))
0976 {
0977 self_type temp(e);
0978 do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
0979 }
0980 else
0981 {
0982 do_bitwise_xor(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
0983 }
0984 return *this;
0985 }
0986
0987 template <class V>
0988 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
0989 operator^=(const V& v)
0990 {
0991 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
0992 using default_ops::eval_bitwise_xor;
0993 eval_bitwise_xor(m_backend, canonical_value(v));
0994 return *this;
0995 }
0996
0997
0998
0999 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(self_type& other) noexcept(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))
1000 {
1001 m_backend.swap(other.backend());
1002 }
1003
1004
1005
1006 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool is_zero() const
1007 {
1008 using default_ops::eval_is_zero;
1009 return eval_is_zero(m_backend);
1010 }
1011 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int sign() const
1012 {
1013 using default_ops::eval_get_sign;
1014 return eval_get_sign(m_backend);
1015 }
1016
1017
1018
1019 std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0)) const
1020 {
1021 return m_backend.str(digits, f);
1022 }
1023
1024 #ifndef BOOST_MP_STANDALONE
1025 template <class Archive>
1026 void serialize(Archive& ar, const unsigned int )
1027 {
1028 ar& boost::make_nvp("backend", m_backend);
1029 }
1030 #endif
1031
1032 private:
1033 template <class T>
1034 BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(T* result) const
1035 {
1036 using default_ops::eval_convert_to;
1037 eval_convert_to(result, m_backend);
1038 }
1039 template <class B2, expression_template_option ET>
1040 BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(number<B2, ET>* result) const
1041 {
1042 result->assign(*this);
1043 }
1044 BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(std::string* result) const
1045 {
1046 *result = this->str();
1047 }
1048
1049 public:
1050 template <class T>
1051 BOOST_MP_CXX14_CONSTEXPR T convert_to() const
1052 {
1053 T result = T();
1054 convert_to_imp(&result);
1055 return result;
1056 }
1057
1058
1059
1060 #if BOOST_WORKAROUND(BOOST_MSVC, < 1900) || (defined(__apple_build_version__) && BOOST_WORKAROUND(__clang_major__, < 9))
1061 template <class T>
1062 #else
1063 template <class T, class = typename std::enable_if<std::is_enum<T>::value || !(std::is_constructible<T, detail::convertible_to<self_type const&> >::value || !std::is_default_constructible<T>::value || (!boost::multiprecision::detail::is_arithmetic<T>::value && !boost::multiprecision::detail::is_complex<T>::value)), T>::type>
1064 #endif
1065 explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
1066 {
1067 return this->template convert_to<T>();
1068 }
1069 BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
1070 {
1071 return !is_zero();
1072 }
1073
1074
1075
1076 static BOOST_MP_CXX14_CONSTEXPR unsigned default_precision() noexcept
1077 {
1078 return Backend::default_precision();
1079 }
1080 static BOOST_MP_CXX14_CONSTEXPR void default_precision(unsigned digits10)
1081 {
1082 Backend::default_precision(digits10);
1083 Backend::thread_default_precision(digits10);
1084 }
1085 static BOOST_MP_CXX14_CONSTEXPR unsigned thread_default_precision() noexcept
1086 {
1087 return Backend::thread_default_precision();
1088 }
1089 static BOOST_MP_CXX14_CONSTEXPR void thread_default_precision(unsigned digits10)
1090 {
1091 Backend::thread_default_precision(digits10);
1092 }
1093 BOOST_MP_CXX14_CONSTEXPR unsigned precision() const noexcept
1094 {
1095 return m_backend.precision();
1096 }
1097 BOOST_MP_CXX14_CONSTEXPR void precision(unsigned digits10)
1098 {
1099 m_backend.precision(digits10);
1100 }
1101
1102
1103
1104 static constexpr variable_precision_options default_variable_precision_options()noexcept
1105 {
1106 return Backend::default_variable_precision_options();
1107 }
1108 static constexpr variable_precision_options thread_default_variable_precision_options()noexcept
1109 {
1110 return Backend::thread_default_variable_precision_options();
1111 }
1112 static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts)
1113 {
1114 Backend::default_variable_precision_options(opts);
1115 Backend::thread_default_variable_precision_options(opts);
1116 }
1117 static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts)
1118 {
1119 Backend::thread_default_variable_precision_options(opts);
1120 }
1121
1122
1123
1124 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int compare(const number<Backend, ExpressionTemplates>& o) const
1125 noexcept(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))
1126 {
1127 return m_backend.compare(o.m_backend);
1128 }
1129 template <class V>
1130 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value != number_kind_complex), int>::type compare(const V& o) const
1131 {
1132 using default_ops::eval_get_sign;
1133 if (o == 0)
1134 return eval_get_sign(m_backend);
1135 return m_backend.compare(canonical_value(o));
1136 }
1137 template <class V>
1138 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value == number_kind_complex), int>::type compare(const V& o) const
1139 {
1140 using default_ops::eval_get_sign;
1141 return m_backend.compare(canonical_value(o));
1142 }
1143
1144
1145
1146 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend& backend() & noexcept
1147 {
1148 return m_backend;
1149 }
1150 BOOST_MP_FORCEINLINE constexpr const Backend& backend() const& noexcept { return m_backend; }
1151 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend&& backend() && noexcept { return static_cast<Backend&&>(m_backend); }
1152 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend const&& backend() const&& noexcept { return static_cast<Backend const&&>(m_backend); }
1153
1154
1155
1156 BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
1157 real() const
1158 {
1159 using default_ops::eval_real;
1160 detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
1161 typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
1162 eval_real(result.backend(), backend());
1163 return result;
1164 }
1165 BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
1166 imag() const
1167 {
1168 using default_ops::eval_imag;
1169 detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
1170 typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
1171 eval_imag(result.backend(), backend());
1172 return result;
1173 }
1174 template <class T>
1175 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value, self_type&>::type real(const T& val)
1176 {
1177 using default_ops::eval_set_real;
1178 eval_set_real(backend(), canonical_value(val));
1179 return *this;
1180 }
1181 template <class T>
1182 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value && number_category<self_type>::value == number_kind_complex, self_type&>::type imag(const T& val)
1183 {
1184 using default_ops::eval_set_imag;
1185 eval_set_imag(backend(), canonical_value(val));
1186 return *this;
1187 }
1188
1189 private:
1190 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1191 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
1192 do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
1193 {
1194
1195
1196 using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
1197 temp_type t(e);
1198 *this = std::move(t);
1199 }
1200 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1201 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
1202 do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
1203 {
1204
1205
1206 using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
1207 temp_type t(e);
1208 this->assign(t);
1209 }
1210
1211 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1212 BOOST_MP_CXX14_CONSTEXPR void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, true>&)
1213 {
1214 do_assign(e, tag());
1215 }
1216
1217 template <class Exp>
1218 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::add_immediates&)
1219 {
1220 using default_ops::eval_add;
1221 boost::multiprecision::detail::maybe_promote_precision(this);
1222 eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1223 }
1224 template <class Exp>
1225 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::subtract_immediates&)
1226 {
1227 using default_ops::eval_subtract;
1228 boost::multiprecision::detail::maybe_promote_precision(this);
1229 eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1230 }
1231 template <class Exp>
1232 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_immediates&)
1233 {
1234 using default_ops::eval_multiply;
1235 boost::multiprecision::detail::maybe_promote_precision(this);
1236 eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1237 }
1238 template <class Exp>
1239 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_add&)
1240 {
1241 using default_ops::eval_multiply_add;
1242 boost::multiprecision::detail::maybe_promote_precision(this);
1243 eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
1244 }
1245 template <class Exp>
1246 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_subtract&)
1247 {
1248 using default_ops::eval_multiply_subtract;
1249 boost::multiprecision::detail::maybe_promote_precision(this);
1250 eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
1251 }
1252
1253 template <class Exp>
1254 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divide_immediates&)
1255 {
1256 using default_ops::eval_divide;
1257 boost::multiprecision::detail::maybe_promote_precision(this);
1258 eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1259 }
1260
1261 template <class Exp>
1262 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::negate&)
1263 {
1264 using left_type = typename Exp::left_type;
1265 do_assign(e.left(), typename left_type::tag_type());
1266 m_backend.negate();
1267 }
1268 template <class Exp>
1269 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::plus&)
1270 {
1271 using left_type = typename Exp::left_type ;
1272 using right_type = typename Exp::right_type;
1273
1274 constexpr int const left_depth = left_type::depth;
1275 constexpr int const right_depth = right_type::depth;
1276
1277 bool bl = contains_self(e.left());
1278 bool br = contains_self(e.right());
1279
1280 if (bl && br)
1281 {
1282 self_type temp(e);
1283 temp.m_backend.swap(this->m_backend);
1284 }
1285 else if (bl && is_self(e.left()))
1286 {
1287
1288 do_add(e.right(), typename right_type::tag_type());
1289 }
1290 else if (br && is_self(e.right()))
1291 {
1292
1293 do_add(e.left(), typename left_type::tag_type());
1294 }
1295 else if (!br && (bl || (left_depth >= right_depth)))
1296 {
1297 do_assign(e.left(), typename left_type::tag_type());
1298 do_add(e.right(), typename right_type::tag_type());
1299 }
1300 else
1301 {
1302 do_assign(e.right(), typename right_type::tag_type());
1303 do_add(e.left(), typename left_type::tag_type());
1304 }
1305 }
1306 template <class Exp>
1307 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::minus&)
1308 {
1309 using left_type = typename Exp::left_type ;
1310 using right_type = typename Exp::right_type;
1311
1312 constexpr int const left_depth = left_type::depth;
1313 constexpr int const right_depth = right_type::depth;
1314
1315 bool bl = contains_self(e.left());
1316 bool br = contains_self(e.right());
1317
1318 if (bl && br)
1319 {
1320 self_type temp(e);
1321 temp.m_backend.swap(this->m_backend);
1322 }
1323 else if (bl && is_self(e.left()))
1324 {
1325
1326 do_subtract(e.right(), typename right_type::tag_type());
1327 }
1328 else if (br && is_self(e.right()))
1329 {
1330
1331 do_subtract(e.left(), typename left_type::tag_type());
1332 m_backend.negate();
1333 }
1334 else if (!br && (bl || (left_depth >= right_depth)))
1335 {
1336 do_assign(e.left(), typename left_type::tag_type());
1337 do_subtract(e.right(), typename right_type::tag_type());
1338 }
1339 else
1340 {
1341 do_assign(e.right(), typename right_type::tag_type());
1342 do_subtract(e.left(), typename left_type::tag_type());
1343 m_backend.negate();
1344 }
1345 }
1346 template <class Exp>
1347 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiplies&)
1348 {
1349 using left_type = typename Exp::left_type ;
1350 using right_type = typename Exp::right_type;
1351
1352 constexpr int const left_depth = left_type::depth;
1353 constexpr int const right_depth = right_type::depth;
1354
1355 bool bl = contains_self(e.left());
1356 bool br = contains_self(e.right());
1357
1358 if (bl && br)
1359 {
1360 self_type temp(e);
1361 temp.m_backend.swap(this->m_backend);
1362 }
1363 else if (bl && is_self(e.left()))
1364 {
1365
1366 do_multiplies(e.right(), typename right_type::tag_type());
1367 }
1368 else if (br && is_self(e.right()))
1369 {
1370
1371 do_multiplies(e.left(), typename left_type::tag_type());
1372 }
1373 else if (!br && (bl || (left_depth >= right_depth)))
1374 {
1375 do_assign(e.left(), typename left_type::tag_type());
1376 do_multiplies(e.right(), typename right_type::tag_type());
1377 }
1378 else
1379 {
1380 do_assign(e.right(), typename right_type::tag_type());
1381 do_multiplies(e.left(), typename left_type::tag_type());
1382 }
1383 }
1384 template <class Exp>
1385 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divides&)
1386 {
1387 using left_type = typename Exp::left_type ;
1388 using right_type = typename Exp::right_type;
1389
1390 bool bl = contains_self(e.left());
1391 bool br = contains_self(e.right());
1392
1393 if (bl && is_self(e.left()))
1394 {
1395
1396 do_divide(e.right(), typename right_type::tag_type());
1397 }
1398 else if (br)
1399 {
1400 self_type temp(e);
1401 temp.m_backend.swap(this->m_backend);
1402 }
1403 else
1404 {
1405 do_assign(e.left(), typename left_type::tag_type());
1406 do_divide(e.right(), typename right_type::tag_type());
1407 }
1408 }
1409 template <class Exp>
1410 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus&)
1411 {
1412
1413
1414
1415 static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
1416
1417 using left_type = typename Exp::left_type ;
1418 using right_type = typename Exp::right_type;
1419
1420 bool bl = contains_self(e.left());
1421 bool br = contains_self(e.right());
1422
1423 if (bl && is_self(e.left()))
1424 {
1425
1426 do_modulus(e.right(), typename right_type::tag_type());
1427 }
1428 else if (br)
1429 {
1430 self_type temp(e);
1431 temp.m_backend.swap(this->m_backend);
1432 }
1433 else
1434 {
1435 do_assign(e.left(), typename left_type::tag_type());
1436 do_modulus(e.right(), typename right_type::tag_type());
1437 }
1438 }
1439 template <class Exp>
1440 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus_immediates&)
1441 {
1442 static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
1443 using default_ops::eval_modulus;
1444 boost::multiprecision::detail::maybe_promote_precision(this);
1445 eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1446 }
1447
1448 template <class Exp>
1449 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and&)
1450 {
1451
1452
1453
1454 static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1455
1456 using left_type = typename Exp::left_type ;
1457 using right_type = typename Exp::right_type;
1458
1459 constexpr int const left_depth = left_type::depth;
1460 constexpr int const right_depth = right_type::depth;
1461
1462 bool bl = contains_self(e.left());
1463 bool br = contains_self(e.right());
1464
1465 if (bl && is_self(e.left()))
1466 {
1467
1468 do_bitwise_and(e.right(), typename right_type::tag_type());
1469 }
1470 else if (br && is_self(e.right()))
1471 {
1472 do_bitwise_and(e.left(), typename left_type::tag_type());
1473 }
1474 else if (!br && (bl || (left_depth >= right_depth)))
1475 {
1476 do_assign(e.left(), typename left_type::tag_type());
1477 do_bitwise_and(e.right(), typename right_type::tag_type());
1478 }
1479 else
1480 {
1481 do_assign(e.right(), typename right_type::tag_type());
1482 do_bitwise_and(e.left(), typename left_type::tag_type());
1483 }
1484 }
1485 template <class Exp>
1486 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
1487 {
1488 static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1489 using default_ops::eval_bitwise_and;
1490 eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1491 }
1492
1493 template <class Exp>
1494 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or&)
1495 {
1496
1497
1498
1499 static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1500
1501 using left_type = typename Exp::left_type ;
1502 using right_type = typename Exp::right_type;
1503
1504 constexpr int const left_depth = left_type::depth;
1505 constexpr int const right_depth = right_type::depth;
1506
1507 bool bl = contains_self(e.left());
1508 bool br = contains_self(e.right());
1509
1510 if (bl && is_self(e.left()))
1511 {
1512
1513 do_bitwise_or(e.right(), typename right_type::tag_type());
1514 }
1515 else if (br && is_self(e.right()))
1516 {
1517 do_bitwise_or(e.left(), typename left_type::tag_type());
1518 }
1519 else if (!br && (bl || (left_depth >= right_depth)))
1520 {
1521 do_assign(e.left(), typename left_type::tag_type());
1522 do_bitwise_or(e.right(), typename right_type::tag_type());
1523 }
1524 else
1525 {
1526 do_assign(e.right(), typename right_type::tag_type());
1527 do_bitwise_or(e.left(), typename left_type::tag_type());
1528 }
1529 }
1530 template <class Exp>
1531 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
1532 {
1533 static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1534 using default_ops::eval_bitwise_or;
1535 eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1536 }
1537
1538 template <class Exp>
1539 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor&)
1540 {
1541
1542
1543
1544 static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1545
1546 using left_type = typename Exp::left_type ;
1547 using right_type = typename Exp::right_type;
1548
1549 constexpr int const left_depth = left_type::depth;
1550 constexpr int const right_depth = right_type::depth;
1551
1552 bool bl = contains_self(e.left());
1553 bool br = contains_self(e.right());
1554
1555 if (bl && is_self(e.left()))
1556 {
1557
1558 do_bitwise_xor(e.right(), typename right_type::tag_type());
1559 }
1560 else if (br && is_self(e.right()))
1561 {
1562 do_bitwise_xor(e.left(), typename left_type::tag_type());
1563 }
1564 else if (!br && (bl || (left_depth >= right_depth)))
1565 {
1566 do_assign(e.left(), typename left_type::tag_type());
1567 do_bitwise_xor(e.right(), typename right_type::tag_type());
1568 }
1569 else
1570 {
1571 do_assign(e.right(), typename right_type::tag_type());
1572 do_bitwise_xor(e.left(), typename left_type::tag_type());
1573 }
1574 }
1575 template <class Exp>
1576 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
1577 {
1578 static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1579 using default_ops::eval_bitwise_xor;
1580 eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1581 }
1582 template <class Exp>
1583 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::terminal&)
1584 {
1585 if (!is_self(e))
1586 {
1587 m_backend = canonical_value(e.value());
1588 }
1589 }
1590 template <class Exp>
1591 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::function&)
1592 {
1593 using tag_type = typename Exp::arity;
1594 boost::multiprecision::detail::maybe_promote_precision(this);
1595 do_assign_function(e, tag_type());
1596 }
1597 template <class Exp>
1598 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_left&)
1599 {
1600
1601 using left_type = typename Exp::left_type ;
1602 using right_type = typename Exp::right_type ;
1603 using right_arity = typename right_type::arity;
1604 static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
1605 using right_value_type = typename right_type::result_type;
1606 static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
1607 using tag_type = typename left_type::tag_type;
1608 do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type());
1609 }
1610
1611 template <class Exp>
1612 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_right&)
1613 {
1614
1615 using left_type = typename Exp::left_type ;
1616 using right_type = typename Exp::right_type ;
1617 using right_arity = typename right_type::arity;
1618 static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
1619 using right_value_type = typename right_type::result_type;
1620 static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
1621 using tag_type = typename left_type::tag_type;
1622 do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type());
1623 }
1624
1625 template <class Exp>
1626 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_complement&)
1627 {
1628 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
1629 using default_ops::eval_complement;
1630 self_type temp(e.left());
1631 eval_complement(m_backend, temp.backend());
1632 }
1633
1634 template <class Exp>
1635 BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::complement_immediates&)
1636 {
1637 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
1638 using default_ops::eval_complement;
1639 eval_complement(m_backend, canonical_value(e.left().value()));
1640 }
1641
1642 template <class Exp, class Val>
1643 BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
1644 {
1645 static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
1646 using default_ops::eval_right_shift;
1647 detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
1648 eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
1649 }
1650
1651 template <class Exp, class Val>
1652 BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
1653 {
1654 static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
1655 using default_ops::eval_left_shift;
1656 detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
1657 eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
1658 }
1659
1660 template <class Exp, class Val, class Tag>
1661 BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
1662 {
1663 static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
1664 using default_ops::eval_right_shift;
1665 self_type temp(e);
1666 detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
1667 eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
1668 }
1669
1670 template <class Exp, class Val, class Tag>
1671 BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
1672 {
1673 static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
1674 using default_ops::eval_left_shift;
1675 self_type temp(e);
1676 detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
1677 eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
1678 }
1679
1680 template <class Exp>
1681 BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 1>&)
1682 {
1683 e.left().value()(&m_backend);
1684 }
1685 template <class Exp>
1686 BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 2>&)
1687 {
1688 using right_type = typename Exp::right_type ;
1689 using tag_type = typename right_type::tag_type;
1690 do_assign_function_1(e.left().value(), e.right_ref(), tag_type());
1691 }
1692 template <class F, class Exp>
1693 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
1694 {
1695 f(m_backend, function_arg_value(val));
1696 }
1697 template <class F, class Exp, class Tag>
1698 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const Tag&)
1699 {
1700 typename Exp::result_type t(val);
1701 f(m_backend, t.backend());
1702 }
1703 template <class Exp>
1704 BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 3>&)
1705 {
1706 using middle_type = typename Exp::middle_type ;
1707 using tag_type = typename middle_type::tag_type;
1708 using end_type = typename Exp::right_type ;
1709 using end_tag = typename end_type::tag_type ;
1710 do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag());
1711 }
1712 template <class F, class Exp1, class Exp2>
1713 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)
1714 {
1715 f(m_backend, function_arg_value(val1), function_arg_value(val2));
1716 }
1717 template <class F, class Exp1, class Exp2, class Tag1>
1718 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)
1719 {
1720 typename Exp1::result_type temp1(val1);
1721 f(m_backend, std::move(temp1.backend()), function_arg_value(val2));
1722 }
1723 template <class F, class Exp1, class Exp2, class Tag2>
1724 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)
1725 {
1726 typename Exp2::result_type temp2(val2);
1727 f(m_backend, function_arg_value(val1), std::move(temp2.backend()));
1728 }
1729 template <class F, class Exp1, class Exp2, class Tag1, class Tag2>
1730 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)
1731 {
1732 typename Exp1::result_type temp1(val1);
1733 typename Exp2::result_type temp2(val2);
1734 f(m_backend, std::move(temp1.backend()), std::move(temp2.backend()));
1735 }
1736
1737 template <class Exp>
1738 BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 4>&)
1739 {
1740 using left_type = typename Exp::left_middle_type ;
1741 using left_tag_type = typename left_type::tag_type ;
1742 using middle_type = typename Exp::right_middle_type;
1743 using middle_tag_type = typename middle_type::tag_type ;
1744 using right_type = typename Exp::right_type ;
1745 using right_tag_type = typename right_type::tag_type ;
1746 do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type());
1747 }
1748
1749 template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
1750 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)
1751 {
1752 do_assign_function_3b(f, val1, val2, val3, t2, t3);
1753 }
1754 template <class F, class Exp1, class Exp2, class Exp3, class Tag1, class Tag2, class Tag3>
1755 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)
1756 {
1757 typename Exp1::result_type t(val1);
1758 do_assign_function_3b(f, std::move(t), val2, val3, t2, t3);
1759 }
1760 template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
1761 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)
1762 {
1763 do_assign_function_3c(f, val1, val2, val3, t3);
1764 }
1765 template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
1766 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& , const Tag3& t3)
1767 {
1768 typename Exp2::result_type t(val2);
1769 do_assign_function_3c(f, val1, std::move(t), val3, t3);
1770 }
1771 template <class F, class Exp1, class Exp2, class Exp3>
1772 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)
1773 {
1774 f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));
1775 }
1776 template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
1777 BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& )
1778 {
1779 typename Exp3::result_type t(val3);
1780 do_assign_function_3c(f, val1, val2, std::move(t), detail::terminal());
1781 }
1782
1783 template <class Exp>
1784 BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::terminal&)
1785 {
1786 using default_ops::eval_add;
1787 boost::multiprecision::detail::maybe_promote_precision(this);
1788 eval_add(m_backend, canonical_value(e.value()));
1789 }
1790
1791 template <class Exp>
1792 BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::negate&)
1793 {
1794 using left_type = typename Exp::left_type;
1795 boost::multiprecision::detail::maybe_promote_precision(this);
1796 do_subtract(e.left(), typename left_type::tag_type());
1797 }
1798
1799 template <class Exp>
1800 BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::plus&)
1801 {
1802 using left_type = typename Exp::left_type ;
1803 using right_type = typename Exp::right_type;
1804 do_add(e.left(), typename left_type::tag_type());
1805 do_add(e.right(), typename right_type::tag_type());
1806 }
1807
1808 template <class Exp>
1809 BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::minus&)
1810 {
1811 using left_type = typename Exp::left_type ;
1812 using right_type = typename Exp::right_type;
1813 do_add(e.left(), typename left_type::tag_type());
1814 do_subtract(e.right(), typename right_type::tag_type());
1815 }
1816
1817 template <class Exp, class unknown>
1818 BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const unknown&)
1819 {
1820 self_type temp(e);
1821 do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1822 }
1823
1824 template <class Exp>
1825 BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::add_immediates&)
1826 {
1827 using default_ops::eval_add;
1828 boost::multiprecision::detail::maybe_promote_precision(this);
1829 eval_add(m_backend, canonical_value(e.left().value()));
1830 eval_add(m_backend, canonical_value(e.right().value()));
1831 }
1832 template <class Exp>
1833 BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::subtract_immediates&)
1834 {
1835 using default_ops::eval_add;
1836 using default_ops::eval_subtract;
1837 boost::multiprecision::detail::maybe_promote_precision(this);
1838 eval_add(m_backend, canonical_value(e.left().value()));
1839 eval_subtract(m_backend, canonical_value(e.right().value()));
1840 }
1841 template <class Exp>
1842 BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::terminal&)
1843 {
1844 using default_ops::eval_subtract;
1845 boost::multiprecision::detail::maybe_promote_precision(this);
1846 eval_subtract(m_backend, canonical_value(e.value()));
1847 }
1848
1849 template <class Exp>
1850 BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::negate&)
1851 {
1852 using left_type = typename Exp::left_type;
1853 do_add(e.left(), typename left_type::tag_type());
1854 }
1855
1856 template <class Exp>
1857 BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::plus&)
1858 {
1859 using left_type = typename Exp::left_type ;
1860 using right_type = typename Exp::right_type;
1861 do_subtract(e.left(), typename left_type::tag_type());
1862 do_subtract(e.right(), typename right_type::tag_type());
1863 }
1864
1865 template <class Exp>
1866 BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::minus&)
1867 {
1868 using left_type = typename Exp::left_type ;
1869 using right_type = typename Exp::right_type;
1870 do_subtract(e.left(), typename left_type::tag_type());
1871 do_add(e.right(), typename right_type::tag_type());
1872 }
1873 template <class Exp>
1874 BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::add_immediates&)
1875 {
1876 using default_ops::eval_subtract;
1877 boost::multiprecision::detail::maybe_promote_precision(this);
1878 eval_subtract(m_backend, canonical_value(e.left().value()));
1879 eval_subtract(m_backend, canonical_value(e.right().value()));
1880 }
1881 template <class Exp>
1882 BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::subtract_immediates&)
1883 {
1884 using default_ops::eval_add;
1885 using default_ops::eval_subtract;
1886 eval_subtract(m_backend, canonical_value(e.left().value()));
1887 eval_add(m_backend, canonical_value(e.right().value()));
1888 }
1889 template <class Exp, class unknown>
1890 BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const unknown&)
1891 {
1892 self_type temp(e);
1893 do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1894 }
1895
1896 template <class Exp>
1897 BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::terminal&)
1898 {
1899 using default_ops::eval_multiply;
1900 boost::multiprecision::detail::maybe_promote_precision(this);
1901 eval_multiply(m_backend, canonical_value(e.value()));
1902 }
1903
1904 template <class Exp>
1905 BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::negate&)
1906 {
1907 using left_type = typename Exp::left_type;
1908 do_multiplies(e.left(), typename left_type::tag_type());
1909 m_backend.negate();
1910 }
1911
1912 template <class Exp>
1913 BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiplies&)
1914 {
1915 using left_type = typename Exp::left_type ;
1916 using right_type = typename Exp::right_type;
1917 do_multiplies(e.left(), typename left_type::tag_type());
1918 do_multiplies(e.right(), typename right_type::tag_type());
1919 }
1920
1921
1922
1923
1924 template <class Exp>
1925 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
1926 do_multiplies(const Exp& e, const detail::divides&)
1927 {
1928 using left_type = typename Exp::left_type ;
1929 using right_type = typename Exp::right_type;
1930 do_multiplies(e.left(), typename left_type::tag_type());
1931 do_divide(e.right(), typename right_type::tag_type());
1932 }
1933
1934 template <class Exp>
1935 BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiply_immediates&)
1936 {
1937 using default_ops::eval_multiply;
1938 boost::multiprecision::detail::maybe_promote_precision(this);
1939 eval_multiply(m_backend, canonical_value(e.left().value()));
1940 eval_multiply(m_backend, canonical_value(e.right().value()));
1941 }
1942
1943
1944
1945
1946 template <class Exp>
1947 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
1948 do_multiplies(const Exp& e, const detail::divide_immediates&)
1949 {
1950 using default_ops::eval_divide;
1951 using default_ops::eval_multiply;
1952 boost::multiprecision::detail::maybe_promote_precision(this);
1953 eval_multiply(m_backend, canonical_value(e.left().value()));
1954 eval_divide(m_backend, canonical_value(e.right().value()));
1955 }
1956 template <class Exp, class unknown>
1957 BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const unknown&)
1958 {
1959 using default_ops::eval_multiply;
1960 boost::multiprecision::detail::maybe_promote_precision(this);
1961 self_type temp(e);
1962 eval_multiply(m_backend, temp.m_backend);
1963 }
1964
1965 template <class Exp>
1966 BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::terminal&)
1967 {
1968 using default_ops::eval_divide;
1969 boost::multiprecision::detail::maybe_promote_precision(this);
1970 eval_divide(m_backend, canonical_value(e.value()));
1971 }
1972
1973 template <class Exp>
1974 BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::negate&)
1975 {
1976 using left_type = typename Exp::left_type;
1977 do_divide(e.left(), typename left_type::tag_type());
1978 m_backend.negate();
1979 }
1980
1981
1982
1983
1984 template <class Exp>
1985 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
1986 do_divide(const Exp& e, const detail::multiplies&)
1987 {
1988 using left_type = typename Exp::left_type ;
1989 using right_type = typename Exp::right_type;
1990 do_divide(e.left(), typename left_type::tag_type());
1991 do_divide(e.right(), typename right_type::tag_type());
1992 }
1993
1994
1995
1996
1997 template <class Exp>
1998 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
1999 do_divide(const Exp& e, const detail::divides&)
2000 {
2001 using left_type = typename Exp::left_type ;
2002 using right_type = typename Exp::right_type;
2003 do_divide(e.left(), typename left_type::tag_type());
2004 do_multiplies(e.right(), typename right_type::tag_type());
2005 }
2006
2007
2008
2009
2010 template <class Exp>
2011 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
2012 do_divides(const Exp& e, const detail::multiply_immediates&)
2013 {
2014 using default_ops::eval_divide;
2015 boost::multiprecision::detail::maybe_promote_precision(this);
2016 eval_divide(m_backend, canonical_value(e.left().value()));
2017 eval_divide(m_backend, canonical_value(e.right().value()));
2018 }
2019
2020
2021
2022
2023 template <class Exp>
2024 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
2025 do_divides(const Exp& e, const detail::divide_immediates&)
2026 {
2027 using default_ops::eval_divide;
2028 using default_ops::eval_multiply;
2029 boost::multiprecision::detail::maybe_promote_precision(this);
2030 eval_divide(m_backend, canonical_value(e.left().value()));
2031 mutiply(m_backend, canonical_value(e.right().value()));
2032 }
2033
2034 template <class Exp, class unknown>
2035 BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const unknown&)
2036 {
2037 using default_ops::eval_multiply;
2038 boost::multiprecision::detail::maybe_promote_precision(this);
2039 self_type temp(e);
2040 eval_divide(m_backend, temp.m_backend);
2041 }
2042
2043 template <class Exp>
2044 BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const detail::terminal&)
2045 {
2046 static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
2047 using default_ops::eval_modulus;
2048 boost::multiprecision::detail::maybe_promote_precision(this);
2049 eval_modulus(m_backend, canonical_value(e.value()));
2050 }
2051
2052 template <class Exp, class Unknown>
2053 BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const Unknown&)
2054 {
2055 static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
2056 using default_ops::eval_modulus;
2057 boost::multiprecision::detail::maybe_promote_precision(this);
2058 self_type temp(e);
2059 eval_modulus(m_backend, canonical_value(temp));
2060 }
2061
2062 template <class Exp>
2063 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::terminal&)
2064 {
2065 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
2066 using default_ops::eval_bitwise_and;
2067 eval_bitwise_and(m_backend, canonical_value(e.value()));
2068 }
2069 template <class Exp>
2070 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
2071 {
2072 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
2073 using left_type = typename Exp::left_type ;
2074 using right_type = typename Exp::right_type;
2075 do_bitwise_and(e.left(), typename left_type::tag_type());
2076 do_bitwise_and(e.right(), typename right_type::tag_type());
2077 }
2078 template <class Exp, class unknown>
2079 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const unknown&)
2080 {
2081 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
2082 using default_ops::eval_bitwise_and;
2083 self_type temp(e);
2084 eval_bitwise_and(m_backend, temp.m_backend);
2085 }
2086
2087 template <class Exp>
2088 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::terminal&)
2089 {
2090 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
2091 using default_ops::eval_bitwise_or;
2092 eval_bitwise_or(m_backend, canonical_value(e.value()));
2093 }
2094 template <class Exp>
2095 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
2096 {
2097 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
2098 using left_type = typename Exp::left_type ;
2099 using right_type = typename Exp::right_type;
2100 do_bitwise_or(e.left(), typename left_type::tag_type());
2101 do_bitwise_or(e.right(), typename right_type::tag_type());
2102 }
2103 template <class Exp, class unknown>
2104 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const unknown&)
2105 {
2106 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
2107 using default_ops::eval_bitwise_or;
2108 self_type temp(e);
2109 eval_bitwise_or(m_backend, temp.m_backend);
2110 }
2111
2112 template <class Exp>
2113 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::terminal&)
2114 {
2115 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
2116 using default_ops::eval_bitwise_xor;
2117 eval_bitwise_xor(m_backend, canonical_value(e.value()));
2118 }
2119 template <class Exp>
2120 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
2121 {
2122 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
2123 using left_type = typename Exp::left_type ;
2124 using right_type = typename Exp::right_type;
2125 do_bitwise_xor(e.left(), typename left_type::tag_type());
2126 do_bitwise_xor(e.right(), typename right_type::tag_type());
2127 }
2128 template <class Exp, class unknown>
2129 BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const unknown&)
2130 {
2131 static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
2132 using default_ops::eval_bitwise_xor;
2133 self_type temp(e);
2134 eval_bitwise_xor(m_backend, temp.m_backend);
2135 }
2136
2137
2138 template <class Exp>
2139 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e) const noexcept
2140 {
2141 return contains_self(e, typename Exp::arity());
2142 }
2143 template <class Exp>
2144 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
2145 {
2146 return is_realy_self(e.value());
2147 }
2148 template <class Exp>
2149 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 1> const&) const noexcept
2150 {
2151 using child_type = typename Exp::left_type;
2152 return contains_self(e.left(), typename child_type::arity());
2153 }
2154 template <class Exp>
2155 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 2> const&) const noexcept
2156 {
2157 using child0_type = typename Exp::left_type ;
2158 using child1_type = typename Exp::right_type;
2159 return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.right(), typename child1_type::arity());
2160 }
2161 template <class Exp>
2162 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 3> const&) const noexcept
2163 {
2164 using child0_type = typename Exp::left_type ;
2165 using child1_type = typename Exp::middle_type;
2166 using child2_type = typename Exp::right_type ;
2167 return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.middle(), typename child1_type::arity()) || contains_self(e.right(), typename child2_type::arity());
2168 }
2169 template <class Exp>
2170 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 4> const&) const noexcept
2171 {
2172 using child0_type = typename Exp::left_type;
2173 using child1_type = typename Exp::left_middle_type;
2174 using child2_type = typename Exp::right_middle_type;
2175 using child3_type = typename Exp::right_type;
2176 return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.left_middle(), typename child1_type::arity()) || contains_self(e.right_middle(), typename child2_type::arity()) || contains_self(e.right(), typename child3_type::arity());
2177 }
2178
2179
2180 template <class Exp>
2181 BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e) const noexcept
2182 {
2183 return is_self(e, typename Exp::arity());
2184 }
2185 template <class Exp>
2186 BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
2187 {
2188 return is_realy_self(e.value());
2189 }
2190 template <class Exp, int v>
2191 BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp&, std::integral_constant<int, v> const&) const noexcept
2192 {
2193 return false;
2194 }
2195
2196 template <class Val>
2197 BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const Val&) const noexcept { return false; }
2198 BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const self_type& v) const noexcept { return &v == this; }
2199
2200 static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const self_type& v) noexcept { return v.backend(); }
2201 template <class Other, expression_template_option ET2>
2202 static BOOST_MP_FORCEINLINE constexpr const Other& function_arg_value(const number<Other, ET2>& v) noexcept { return v.backend(); }
2203 template <class V>
2204 static BOOST_MP_FORCEINLINE constexpr const V& function_arg_value(const V& v) noexcept { return v; }
2205 template <class A1, class A2, class A3, class A4>
2206 static BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) noexcept { return exp.value(); }
2207 template <class A2, class A3, class A4>
2208 static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) noexcept { return exp.value().backend(); }
2209 Backend m_backend;
2210
2211 public:
2212
2213
2214
2215
2216 static BOOST_MP_FORCEINLINE constexpr const Backend& canonical_value(const self_type& v) noexcept { return v.m_backend; }
2217 template <class B2, expression_template_option ET>
2218 static BOOST_MP_FORCEINLINE constexpr const B2& canonical_value(const number<B2, ET>& v) noexcept { return v.backend(); }
2219 template <class B2, expression_template_option ET>
2220 static BOOST_MP_FORCEINLINE constexpr B2&& canonical_value(number<B2, ET>&& v) noexcept { return static_cast<number<B2, ET>&&>(v).backend(); }
2221 template <class V>
2222 static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<!std::is_same<typename detail::canonical<V, Backend>::type, V>::value, typename detail::canonical<V, Backend>::type>::type
2223 canonical_value(const V& v) noexcept { return static_cast<typename detail::canonical<V, Backend>::type>(v); }
2224 template <class V>
2225 static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<std::is_same<typename detail::canonical<V, Backend>::type, V>::value, const V&>::type
2226 canonical_value(const V& v) noexcept { return v; }
2227 static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) noexcept { return v.c_str(); }
2228 };
2229
2230 template <class Backend, expression_template_option ExpressionTemplates>
2231 inline std::ostream& operator<<(std::ostream& os, const number<Backend, ExpressionTemplates>& r)
2232 {
2233 std::streamsize d = os.precision();
2234 std::string s = r.str(d, os.flags());
2235 std::streamsize ss = os.width();
2236 if (ss > static_cast<std::streamsize>(s.size()))
2237 {
2238 char fill = os.fill();
2239 if ((os.flags() & std::ios_base::left) == std::ios_base::left)
2240 s.append(static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
2241 else
2242 s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
2243 }
2244 return os << s;
2245 }
2246
2247 template <class Backend, expression_template_option ExpressionTemplates>
2248 std::string to_string(const number<Backend, ExpressionTemplates>& val)
2249 {
2250 return val.str(6, std::ios_base::fixed|std::ios_base::showpoint);
2251 }
2252
2253 namespace detail {
2254
2255 template <class tag, class A1, class A2, class A3, class A4>
2256 inline std::ostream& operator<<(std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
2257 {
2258 using value_type = typename expression<tag, A1, A2, A3, A4>::result_type;
2259 value_type temp(r);
2260 return os << temp;
2261 }
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271 inline std::string read_string_while(std::istream& is, std::string const& permitted_chars)
2272 {
2273 std::ios_base::iostate state = std::ios_base::goodbit;
2274 const std::istream::sentry sentry_check(is);
2275 std::string result;
2276
2277 if (sentry_check)
2278 {
2279 int c = is.rdbuf()->sgetc();
2280
2281 for (;; c = is.rdbuf()->snextc())
2282 if (std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
2283 {
2284 state |= std::ios_base::eofbit;
2285 break;
2286 }
2287 else if (permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
2288 {
2289
2290
2291 break;
2292 }
2293 else
2294 {
2295 result.append(1, std::istream::traits_type::to_char_type(c));
2296 }
2297 }
2298
2299 if (!result.size())
2300 state |= std::ios_base::failbit;
2301 is.setstate(state);
2302 return result;
2303 }
2304
2305 }
2306
2307 template <class Backend, expression_template_option ExpressionTemplates>
2308 inline std::istream& operator>>(std::istream& is, number<Backend, ExpressionTemplates>& r)
2309 {
2310 bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
2311 bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
2312 std::string s;
2313 switch (boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
2314 {
2315 case boost::multiprecision::number_kind_integer:
2316 if (oct_format)
2317 s = detail::read_string_while(is, "+-01234567");
2318 else if (hex_format)
2319 s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");
2320 else
2321 s = detail::read_string_while(is, "+-0123456789");
2322 break;
2323 case boost::multiprecision::number_kind_rational:
2324 if (oct_format)
2325 s = detail::read_string_while(is, "+-01234567/");
2326 else if (hex_format)
2327 s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789/");
2328 else
2329 s = detail::read_string_while(is, "+-0123456789/");
2330 break;
2331 case boost::multiprecision::number_kind_floating_point:
2332 BOOST_IF_CONSTEXPR(std::is_same<number<Backend, ExpressionTemplates>, typename number<Backend, ExpressionTemplates>::value_type>::value)
2333 s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
2334 else
2335
2336 s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY{,}");
2337 break;
2338 case boost::multiprecision::number_kind_complex:
2339 s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY,()");
2340 break;
2341 default:
2342 is >> s;
2343 }
2344 if (s.size())
2345 {
2346 if (hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))
2347 s.insert(s.find_first_not_of("+-"), "0x");
2348 if (oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))
2349 s.insert(s.find_first_not_of("+-"), "0");
2350 r.assign(s);
2351 }
2352 else if (!is.fail())
2353 is.setstate(std::istream::failbit);
2354 return is;
2355 }
2356
2357 template <class Backend, expression_template_option ExpressionTemplates>
2358 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b)
2359 noexcept(noexcept(std::declval<number<Backend, ExpressionTemplates>&>() = std::declval<number<Backend, ExpressionTemplates>&>()))
2360 {
2361 a.swap(b);
2362 }
2363
2364
2365
2366 template <class Backend, expression_template_option ExpressionTemplates>
2367 inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
2368 {
2369 return hash_value(val.backend());
2370 }
2371
2372 namespace detail {
2373
2374 BOOST_MP_FORCEINLINE bool istream_peek(std::istream& is, char& c, bool have_hex)
2375 {
2376 int i = is.peek();
2377 c = static_cast<char>(i);
2378 return (EOF != i) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')));
2379 }
2380
2381 }
2382
2383 }
2384
2385 template <class T>
2386 class rational;
2387
2388 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2389 inline std::istream& operator>>(std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
2390 {
2391 std::string s1;
2392 multiprecision::number<Backend, ExpressionTemplates> v1, v2;
2393 char c;
2394 bool have_hex = false;
2395 bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
2396 bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
2397
2398 while (multiprecision::detail::istream_peek(is, c, have_hex))
2399 {
2400 if (c == 'x' || c == 'X')
2401 have_hex = true;
2402 s1.append(1, c);
2403 is.get();
2404 }
2405 if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
2406 s1.insert(static_cast<std::string::size_type>(0), "0x");
2407 if (oct_format && (s1[0] != '0'))
2408 s1.insert(static_cast<std::string::size_type>(0), "0");
2409 v1.assign(s1);
2410 s1.erase();
2411 if (c == '/')
2412 {
2413 is.get();
2414 while (multiprecision::detail::istream_peek(is, c, have_hex))
2415 {
2416 if (c == 'x' || c == 'X')
2417 have_hex = true;
2418 s1.append(1, c);
2419 is.get();
2420 }
2421 if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
2422 s1.insert(static_cast<std::string::size_type>(0), "0x");
2423 if (oct_format && (s1[0] != '0'))
2424 s1.insert(static_cast<std::string::size_type>(0), "0");
2425 v2.assign(s1);
2426 }
2427 else
2428 v2 = 1;
2429 r.assign(v1, v2);
2430 return is;
2431 }
2432
2433 template <class T, multiprecision::expression_template_option ExpressionTemplates>
2434 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
2435 {
2436 return a.numerator();
2437 }
2438
2439 template <class T, multiprecision::expression_template_option ExpressionTemplates>
2440 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
2441 {
2442 return a.denominator();
2443 }
2444
2445 template <class T, multiprecision::expression_template_option ExpressionTemplates>
2446 inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const rational<multiprecision::number<T, ExpressionTemplates> >& val)
2447 {
2448 std::size_t result = hash_value(val.numerator());
2449 boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator()));
2450 return result;
2451 }
2452
2453 namespace multiprecision {
2454
2455 template <class I>
2456 struct component_type<boost::rational<I> >
2457 {
2458 using type = I;
2459 };
2460
2461 }
2462
2463 #ifdef BOOST_MSVC
2464 #pragma warning(pop)
2465 #endif
2466
2467 }
2468
2469 namespace std {
2470
2471 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
2472 struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
2473 {
2474 BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val) const { return hash_value(val); }
2475 };
2476 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
2477 struct hash<boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> > >
2478 {
2479 BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> >& val) const
2480 {
2481 std::size_t result = hash_value(val.numerator());
2482 boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator()));
2483 return result;
2484 }
2485 };
2486
2487 }
2488
2489 #include <boost/multiprecision/detail/ublas_interop.hpp>
2490
2491 #endif