Index: boost/multiprecision/cpp_int.hpp =================================================================== --- boost/multiprecision/cpp_int.hpp (revision 84839) +++ boost/multiprecision/cpp_int.hpp (working copy) @@ -19,6 +19,7 @@ #include #include #include +#include #include #ifdef BOOST_MP_USER_DEFINED_LITERALS #include @@ -214,7 +215,7 @@ BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT : m_data(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false), m_internal(true) { } BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT - : m_data(i), m_limbs(i < 0 ? (-i > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)), + : m_data(i), m_limbs(i < 0 ? (static_cast(-i) > static_cast(max_limb_value) ? 2 : 1) : (i > max_limb_value ? 2 : 1)), m_sign(i < 0), m_internal(true) { } #endif // @@ -450,7 +451,7 @@ : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false) {} BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT : m_wrapper(double_limb_type(i < 0 ? -i : i)), - m_limbs(i < 0 ? (-i > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)), + m_limbs(i < 0 ? (static_cast(-i) > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)), m_sign(i < 0) {} #endif #if defined(BOOST_MP_USER_DEFINED_LITERALS) @@ -760,22 +761,22 @@ // template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(i < 0 ? static_cast(-i) : static_cast(i)), m_sign(i < 0) {} + : m_data(i < 0 ? static_cast(static_cast::type>(-i)) & limb_mask : static_cast(i) & limb_mask), m_sign(i < 0) {} template BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(i < 0 ? static_cast(-i) : static_cast(i)), m_sign(i < 0) { check_in_range(i); } + : m_data(i < 0 ? static_cast(static_cast::type>(-i) & limb_mask) : static_cast(i) & limb_mask), m_sign(i < 0) { check_in_range(i); } template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename enable_if_c::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(static_cast(i)), m_sign(false) {} + : m_data(static_cast(i) & limb_mask), m_sign(false) {} template BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename enable_if_c::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(static_cast(i)), m_sign(false) { check_in_range(i); } + : m_data(static_cast(i) & limb_mask), m_sign(false) { check_in_range(i); } template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(F i, typename enable_if_c::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(static_cast(std::fabs(i))), m_sign(i < 0) {} + : m_data(static_cast(std::fabs(i)) & limb_mask), m_sign(i < 0) {} template BOOST_MP_FORCEINLINE cpp_int_base(F i, typename enable_if_c::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(static_cast(std::fabs(i))), m_sign(i < 0) { check_in_range(i); } + : m_data(static_cast(std::fabs(i)) & limb_mask), m_sign(i < 0) { check_in_range(i); } #if defined(BOOST_MP_USER_DEFINED_LITERALS) BOOST_CONSTEXPR cpp_int_base(literals::detail::value_pack<>) : m_data(static_cast(0u)), m_sign(false) {} @@ -855,7 +856,9 @@ typedef const local_limb_type* const_limb_pointer; private: BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT); - BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = (~local_limb_type(0)) >> (limb_bits - MinBits)); + BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = limb_bits != MinBits ? + static_cast(static_cast(~local_limb_type(0)) >> (limb_bits - MinBits)) + : static_cast(~local_limb_type(0))); local_limb_type m_data; @@ -900,19 +903,19 @@ // template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(i < 0 ? 1 + ~static_cast(-i) : static_cast(i)) {} + : m_data(i < 0 ? (1 + ~static_cast(-i)) & limb_mask : static_cast(i) & limb_mask) {} template BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) : m_data(i < 0 ? 1 + ~static_cast(-i) : static_cast(i)) { check_in_range(i); } template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(static_cast(i)) {} + : m_data(static_cast(i) & limb_mask) {} template BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) : m_data(static_cast(i)) { check_in_range(i); } template BOOST_MP_FORCEINLINE cpp_int_base(F i, typename enable_if >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) - : m_data(static_cast(std::fabs(i))) + : m_data(static_cast(std::fabs(i)) & limb_mask) { check_in_range(i); if(i < 0) @@ -1163,8 +1166,9 @@ template typename disable_if >::type do_assign_arithmetic(A val, const mpl::true_&) { + typedef typename make_signed::type signed_limb_type; this->check_in_range(val); - *this->limbs() = (val < 0) ? static_cast(-val) : static_cast(val); + *this->limbs() = (val < 0) ? static_cast(-static_cast(val)) : static_cast(val); this->sign(val < 0); this->normalize(); } Index: libs/multiprecision/test/test_arithmetic.hpp =================================================================== --- libs/multiprecision/test/test_arithmetic.hpp (revision 84839) +++ libs/multiprecision/test/test_arithmetic.hpp (working copy) @@ -839,6 +839,38 @@ }; template +void test_negative_mixed_minmax(boost::mpl::true_ const&) +{ + if(!std::numeric_limits::is_bounded || (std::numeric_limits::digits >= std::numeric_limits::digits)) + { + Real mx1((std::numeric_limits::max)() - 1); + ++mx1; + Real mx2((std::numeric_limits::max)()); + BOOST_CHECK_EQUAL(mx1, mx2); + mx1 = (std::numeric_limits::max)() - 1; + ++mx1; + mx2 = (std::numeric_limits::max)(); + BOOST_CHECK_EQUAL(mx1, mx2); + + if(!std::numeric_limits::is_bounded || (std::numeric_limits::digits > std::numeric_limits::digits)) + { + Real mx3((std::numeric_limits::min)() + 1); + --mx3; + Real mx4((std::numeric_limits::min)()); + BOOST_CHECK_EQUAL(mx3, mx4); + mx3 = (std::numeric_limits::min)() + 1; + --mx3; + mx4 = (std::numeric_limits::min)(); + BOOST_CHECK_EQUAL(mx3, mx4); + } + } +} +template +void test_negative_mixed_minmax(boost::mpl::false_ const&) +{ +} + +template void test_negative_mixed(boost::mpl::true_ const&) { typedef typename lexical_cast_target_type::type target_type; @@ -1111,6 +1143,10 @@ BOOST_CHECK_EQUAL(d , -3 * -4 - -2); d = b * static_cast(n3) - static_cast(n1); BOOST_CHECK_EQUAL(d , -3 * -4 - -2); + // + // Conversion from min and max values: + // + test_negative_mixed_minmax(boost::mpl::bool_::is_integer && std::numeric_limits::is_integer>()); } template