/usr/include/boost/multiprecision
Edit: /usr/include/boost/multiprecision/number.hpp (104027B)
///////////////////////////////////////////////////////////////////////////////
// Copyright 2011 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_EXTENDED_REAL_HPP
#define BOOST_MATH_EXTENDED_REAL_HPP
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include // stream operators
#include // EOF
#include // isspace
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
#include
#endif
namespace boost {
namespace multiprecision {
#ifdef BOOST_MSVC
// warning C4127: conditional expression is constant
// warning C4714: function marked as __forceinline not inlined
#pragma warning(push)
#pragma warning(disable : 4127 4714 6326)
#endif
template
class number
{
typedef number self_type;
public:
typedef Backend backend_type;
typedef typename component_type::type value_type;
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number() BOOST_MP_NOEXCEPT_IF(noexcept(Backend())) {}
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval()))) : m_backend(e.m_backend) {}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename boost::enable_if_c<
(boost::is_arithmetic::value || is_same::value || is_convertible::value) && !is_convertible::type, Backend>::value && !detail::is_restricted_conversion::type, Backend>::value
#ifdef BOOST_HAS_FLOAT128
&& !boost::is_same::value
#endif
>::type* = 0)
{
m_backend = canonical_value(v);
}
template
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
is_convertible::type, Backend>::value && !detail::is_restricted_conversion::type, Backend>::value>::type* = 0)
#ifndef BOOST_INTEL
BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval::type const&>())))
#endif
: m_backend(canonical_value(v))
{}
template
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, unsigned digits10, typename boost::enable_if_c<(boost::is_arithmetic::value || is_same::value || is_convertible::value) && !detail::is_restricted_conversion::type, Backend>::value && (boost::multiprecision::number_category::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category::value != boost::multiprecision::number_kind_rational)
#ifdef BOOST_HAS_FLOAT128
&& !boost::is_same::value
#endif
>::type* = 0)
: m_backend(canonical_value(v), digits10)
{}
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e, unsigned digits10)
BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval(), std::declval())))
: m_backend(e.m_backend, digits10) {}
template
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename boost::enable_if_c<
(boost::is_arithmetic::value || is_same::value || is_convertible::value) && !detail::is_explicitly_convertible::type, Backend>::value && detail::is_restricted_conversion::type, Backend>::value>::type* = 0)
BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval::type const&>()))
{
m_backend = canonical_value(v);
}
template
explicit BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
detail::is_explicitly_convertible::type, Backend>::value && (detail::is_restricted_conversion::type, Backend>::value || !is_convertible::type, Backend>::value)>::type* = 0)
BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval::type const&>())))
: m_backend(canonical_value(v)) {}
template
explicit BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, unsigned digits10, typename boost::enable_if_c<(boost::is_arithmetic::value || is_same::value || is_convertible::value) && detail::is_restricted_conversion::type, Backend>::value && (boost::multiprecision::number_category::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category::value != boost::multiprecision::number_kind_rational)>::type* = 0)
: m_backend(canonical_value(v), digits10) {}
template
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& val)
BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval()))) : m_backend(val.backend()) {}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number& val,
typename boost::enable_if_c<(boost::is_convertible::value && !detail::is_restricted_conversion::value)>::type* = 0)
BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval())))
: m_backend(val.backend()) {}
template
explicit BOOST_MP_CXX14_CONSTEXPR number(const number& val, typename boost::enable_if_c<
(!detail::is_explicitly_convertible::value)>::type* = 0)
{
//
// Attempt a generic interconvertion:
//
detail::scoped_default_precision > precision_guard_1(val);
detail::scoped_default_precision > precision_guard_2(val);
using detail::generic_interconvert;
generic_interconvert(backend(), val.backend(), number_category(), number_category());
}
template
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number& val, typename boost::enable_if_c<
(detail::is_explicitly_convertible::value && (detail::is_restricted_conversion::value || !boost::is_convertible::value))>::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval())))
: m_backend(val.backend()) {}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
typename boost::enable_if_c<(is_convertible::value && is_convertible::value && !is_same::type, self_type>::value)>::type* = 0)
{
using default_ops::assign_components;
detail::scoped_default_precision > precision_guard(v1, v2);
assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
}
template
BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
typename boost::enable_if_c<
(is_constructible::value || is_convertible::value) && (is_constructible::value || is_convertible::value) && !is_same::type, self_type>::value && !is_same::value && !(is_convertible::value && is_convertible::value)>::type* = 0)
{
using default_ops::assign_components;
detail::scoped_default_precision > precision_guard(v1, v2);
assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
}
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
//
// Support for new types in C++17
//
template
explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view& view)
{
using default_ops::assign_from_string_view;
assign_from_string_view(this->backend(), view);
}
template
explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view& view_x, const std::basic_string_view& view_y)
{
using default_ops::assign_from_string_view;
assign_from_string_view(this->backend(), view_x, view_y);
}
template
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view& v, unsigned digits10)
: m_backend(canonical_value(v), digits10) {}
template
BOOST_MP_CXX14_CONSTEXPR number& assign(const std::basic_string_view& view)
{
using default_ops::assign_from_string_view;
assign_from_string_view(this->backend(), view);
return *this;
}
#endif
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
typename boost::enable_if_c<(is_convertible::value && is_convertible::value && !is_same::type, self_type>::value)>::type* = 0)
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10)
{}
template
BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
typename boost::enable_if_c<((is_constructible::value || is_convertible::value) && (is_constructible::value || is_convertible::value) && !is_same::type, self_type>::value) && !(is_convertible::value && is_convertible::value)>::type* = 0)
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10) {}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number& v1, const number& v2, typename boost::enable_if_c::value>::type* = 0)
{
using default_ops::assign_components;
detail::scoped_default_precision > precision_guard(v1, v2);
assign_components(m_backend, v1.backend(), v2.backend());
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator=(const detail::expression& e)
{
typedef mpl::bool_::result_type>::value> tag_type;
detail::scoped_default_precision > precision_guard(e);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(e);
return *this = BOOST_MP_MOVE(t);
}
do_assign(e, tag_type());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression& e)
{
typedef mpl::bool_::result_type>::value> tag_type;
detail::scoped_default_precision > precision_guard(e);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t;
t.assign(e);
return *this = BOOST_MP_MOVE(t);
}
do_assign(e, tag_type());
return *this;
}
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(const number& e)
BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval()))
{
m_backend = e.m_backend;
return *this;
}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type
operator=(const V& v)
BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval::type&>()))
{
m_backend = canonical_value(v);
return *this;
}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& assign(const V& v)
BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval::type&>()))
{
m_backend = canonical_value(v);
return *this;
}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& assign(const V& v, unsigned digits10)
BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval::type&>()))
{
number t(v, digits10);
return *this = t;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if, number&>::type
assign(const number& v)
{
//
// Attempt a generic interconvertion:
//
using detail::generic_interconvert;
detail::scoped_default_precision > precision_guard(v);
detail::scoped_default_precision > precision_guard2(v);
//
// If the current precision of *this differs from that of value v, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(v);
return *this = BOOST_MP_MOVE(t);
}
generic_interconvert(backend(), v.backend(), number_category(), number_category());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR number(const detail::expression& e, typename boost::enable_if_c::result_type, self_type>::value>::type* = 0)
{
//
// No preicsion guard here, we already have one in operator=
//
*this = e;
}
template
explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression& e,
typename boost::enable_if_c::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible::result_type, self_type>::value>::type* = 0)
{
//
// No precision guard as assign has one already:
//
assign(e);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(number&& r)
BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval())))
: m_backend(static_cast(r.m_backend))
{}
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(number&& r) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval() = std::declval()))
{
m_backend = static_cast(r.m_backend);
return *this;
}
#endif
BOOST_MP_CXX14_CONSTEXPR number& operator+=(const self_type& val)
{
detail::scoped_default_precision > precision_guard(*this, val);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(*this + val);
return *this = BOOST_MP_MOVE(t);
}
do_add(detail::expression(val), detail::terminal());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator+=(const detail::expression& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
// Create a copy if e contains this, but not if we're just doing a
// x += x
if ((contains_self(e) && !is_self(e)))
{
self_type temp(e);
do_add(detail::expression(temp), detail::terminal());
}
else
{
do_add(e, tag());
}
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR number& operator+=(const detail::expression& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(*this + e);
return *this = BOOST_MP_MOVE(t);
}
//
// Fused multiply-add:
//
using default_ops::eval_multiply_add;
eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
return *this;
}
template
typename boost::enable_if_c::value, number&>::type
BOOST_MP_CXX14_CONSTEXPR operator+=(const V& v)
{
using default_ops::eval_add;
eval_add(m_backend, canonical_value(v));
return *this;
}
BOOST_MP_CXX14_CONSTEXPR number& operator-=(const self_type& val)
{
detail::scoped_default_precision > precision_guard(*this, val);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(*this - val);
return *this = BOOST_MP_MOVE(t);
}
do_subtract(detail::expression(val), detail::terminal());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator-=(const detail::expression& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
// Create a copy if e contains this:
if (contains_self(e))
{
self_type temp(e);
do_subtract(detail::expression(temp), detail::terminal());
}
else
{
do_subtract(e, typename detail::expression::tag_type());
}
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type
operator-=(const V& v)
{
using default_ops::eval_subtract;
eval_subtract(m_backend, canonical_value(v));
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR number& operator-=(const detail::expression& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(*this - e);
return *this = BOOST_MP_MOVE(t);
}
//
// Fused multiply-subtract:
//
using default_ops::eval_multiply_subtract;
eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
return *this;
}
BOOST_MP_CXX14_CONSTEXPR number& operator*=(const self_type& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(*this * e);
return *this = BOOST_MP_MOVE(t);
}
do_multiplies(detail::expression(e), detail::terminal());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator*=(const detail::expression& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
// Create a temporary if the RHS references *this, but not
// if we're just doing an x *= x;
if ((contains_self(e) && !is_self(e)))
{
self_type temp(e);
do_multiplies(detail::expression(temp), detail::terminal());
}
else
{
do_multiplies(e, typename detail::expression::tag_type());
}
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type
operator*=(const V& v)
{
using default_ops::eval_multiply;
eval_multiply(m_backend, canonical_value(v));
return *this;
}
BOOST_MP_CXX14_CONSTEXPR number& operator%=(const self_type& e)
{
BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types");
detail::scoped_default_precision > precision_guard(*this, e);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(*this % e);
return *this = BOOST_MP_MOVE(t);
}
do_modulus(detail::expression(e), detail::terminal());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator%=(const detail::expression& e)
{
BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types");
detail::scoped_default_precision > precision_guard(*this, e);
// Create a temporary if the RHS references *this:
if (contains_self(e))
{
self_type temp(e);
do_modulus(detail::expression(temp), detail::terminal());
}
else
{
do_modulus(e, typename detail::expression::tag_type());
}
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type
operator%=(const V& v)
{
BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types");
using default_ops::eval_modulus;
eval_modulus(m_backend, canonical_value(v));
return *this;
}
//
// These operators are *not* proto-ized.
// The issue is that the increment/decrement must happen
// even if the result of the operator *is never used*.
// Possibly we could modify our expression wrapper to
// execute the increment/decrement on destruction, but
// correct implementation will be tricky, so defered for now...
//
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator++()
{
using default_ops::eval_increment;
eval_increment(m_backend);
return *this;
}
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator--()
{
using default_ops::eval_decrement;
eval_decrement(m_backend);
return *this;
}
inline BOOST_MP_CXX14_CONSTEXPR number operator++(int)
{
using default_ops::eval_increment;
self_type temp(*this);
eval_increment(m_backend);
return temp;
}
inline BOOST_MP_CXX14_CONSTEXPR number operator--(int)
{
using default_ops::eval_decrement;
self_type temp(*this);
eval_decrement(m_backend);
return temp;
}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator<<=(V val)
{
BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The left-shift operation is only valid for integer types");
detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), mpl::bool_::value>());
eval_left_shift(m_backend, static_cast(canonical_value(val)));
return *this;
}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type operator>>=(V val)
{
BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The right-shift operation is only valid for integer types");
detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), mpl::bool_::value>());
eval_right_shift(m_backend, static_cast(canonical_value(val)));
return *this;
}
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator/=(const self_type& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
// and then move the result into *this. In C++17 we add a leading "if constexpr"
// which causes this code to be eliminated in the common case that this type is
// not actually variable precision. Pre C++17 this code should still be mostly
// optimised away, but we can't prevent instantiation of the dead code leading
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
{
number t(*this / e);
return *this = BOOST_MP_MOVE(t);
}
do_divide(detail::expression(e), detail::terminal());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator/=(const detail::expression& e)
{
detail::scoped_default_precision > precision_guard(*this, e);
// Create a temporary if the RHS references *this:
if (contains_self(e))
{
self_type temp(e);
do_divide(detail::expression(temp), detail::terminal());
}
else
{
do_divide(e, typename detail::expression::tag_type());
}
return *this;
}
template
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::value, number&>::type
operator/=(const V& v)
{
using default_ops::eval_divide;
eval_divide(m_backend, canonical_value(v));
return *this;
}
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator&=(const self_type& e)
{
BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
do_bitwise_and(detail::expression(e), detail::terminal());
return *this;
}
template
BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c::result_type, self_type>::value, number&>::type operator&=(const detail::expression& e)
{
BOOST_STATIC_ASSERT_MSG(number_category