Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84897 - in trunk: boost/multiprecision libs/multiprecision/test
From: john_at_[hidden]
Date: 2013-06-24 06:36:02


Author: johnmaddock
Date: 2013-06-24 06:36:01 EDT (Mon, 24 Jun 2013)
New Revision: 84897
URL: http://svn.boost.org/trac/boost/changeset/84897

Log:
Add some typecasts to ensure conversion from negative values proceeds correctly.
Fix masking of values during construction so overflow wraps around in unchecked fixed precision integers.
Add tests for above changes.
Refs #8711.

Text files modified:
   trunk/boost/multiprecision/cpp_int.hpp | 30 +++++++++++++++++-------------
   trunk/libs/multiprecision/test/test_arithmetic.hpp | 36 ++++++++++++++++++++++++++++++++++++
   2 files changed, 53 insertions(+), 13 deletions(-)

Modified: trunk/boost/multiprecision/cpp_int.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int.hpp Sun Jun 23 20:44:41 2013 (r84896)
+++ trunk/boost/multiprecision/cpp_int.hpp 2013-06-24 06:36:01 EDT (Mon, 24 Jun 2013) (r84897)
@@ -19,6 +19,7 @@
 #include <boost/detail/endian.hpp>
 #include <boost/integer/static_min_max.hpp>
 #include <boost/type_traits/common_type.hpp>
+#include <boost/type_traits/make_signed.hpp>
 #include <boost/multiprecision/cpp_int/checked.hpp>
 #ifdef BOOST_MP_USER_DEFINED_LITERALS
 #include <boost/multiprecision/cpp_int/value_pack.hpp>
@@ -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<double_limb_type>(-i) > static_cast<double_limb_type>(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<double_limb_type>(-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 <class SI>
    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(i < 0 ? static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)), m_sign(i < 0) {}
+ : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask), m_sign(i < 0) {}
    template <class SI>
    BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(i < 0 ? static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)), m_sign(i < 0) { check_in_range(i); }
+ : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(-i) & limb_mask) : static_cast<local_limb_type>(i) & limb_mask), m_sign(i < 0) { check_in_range(i); }
    template <class UI>
    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename enable_if_c<is_unsigned<UI>::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(static_cast<local_limb_type>(i)), m_sign(false) {}
+ : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) {}
    template <class UI>
    BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename enable_if_c<is_unsigned<UI>::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(static_cast<local_limb_type>(i)), m_sign(false) { check_in_range(i); }
+ : m_data(static_cast<local_limb_type>(i) & limb_mask), m_sign(false) { check_in_range(i); }
    template <class F>
    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(F i, typename enable_if_c<is_floating_point<F>::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(static_cast<local_limb_type>(std::fabs(i))), m_sign(i < 0) {}
+ : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask), m_sign(i < 0) {}
    template <class F>
    BOOST_MP_FORCEINLINE cpp_int_base(F i, typename enable_if_c<is_floating_point<F>::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(static_cast<local_limb_type>(std::fabs(i))), m_sign(i < 0) { check_in_range(i); }
+ : m_data(static_cast<local_limb_type>(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<local_limb_type>(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<local_limb_type>(static_cast<local_limb_type>(~local_limb_type(0)) >> (limb_bits - MinBits))
+ : static_cast<local_limb_type>(~local_limb_type(0)));
 
    local_limb_type m_data;
 
@@ -900,19 +903,19 @@
    //
    template <class SI>
    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) {}
+ : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask) {}
    template <class SI>
    BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
       : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i) : static_cast<local_limb_type>(i)) { check_in_range(i); }
    template <class UI>
    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename enable_if_c<is_unsigned<UI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(static_cast<local_limb_type>(i)) {}
+ : m_data(static_cast<local_limb_type>(i) & limb_mask) {}
    template <class UI>
    BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename enable_if_c<is_unsigned<UI>::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
       : m_data(static_cast<local_limb_type>(i)) { check_in_range(i); }
    template <class F>
    BOOST_MP_FORCEINLINE cpp_int_base(F i, typename enable_if<is_floating_point<F> >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked))
- : m_data(static_cast<local_limb_type>(std::fabs(i)))
+ : m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask)
    {
       check_in_range(i);
       if(i < 0)
@@ -1163,8 +1166,9 @@
    template <class A>
    typename disable_if<is_unsigned<A> >::type do_assign_arithmetic(A val, const mpl::true_&)
    {
+ typedef typename make_signed<typename self_type::local_limb_type>::type signed_limb_type;
       this->check_in_range(val);
- *this->limbs() = (val < 0) ? static_cast<typename self_type::local_limb_type>(-val) : static_cast<typename self_type::local_limb_type>(val);
+ *this->limbs() = (val < 0) ? static_cast<typename self_type::local_limb_type>(-static_cast<signed_limb_type>(val)) : static_cast<typename self_type::local_limb_type>(val);
       this->sign(val < 0);
       this->normalize();
    }

Modified: trunk/libs/multiprecision/test/test_arithmetic.hpp
==============================================================================
--- trunk/libs/multiprecision/test/test_arithmetic.hpp Sun Jun 23 20:44:41 2013 (r84896)
+++ trunk/libs/multiprecision/test/test_arithmetic.hpp 2013-06-24 06:36:01 EDT (Mon, 24 Jun 2013) (r84897)
@@ -839,6 +839,38 @@
 };
 
 template <class Real, class Num>
+void test_negative_mixed_minmax(boost::mpl::true_ const&)
+{
+ if(!std::numeric_limits<Real>::is_bounded || (std::numeric_limits<Real>::digits >= std::numeric_limits<Num>::digits))
+ {
+ Real mx1((std::numeric_limits<Num>::max)() - 1);
+ ++mx1;
+ Real mx2((std::numeric_limits<Num>::max)());
+ BOOST_CHECK_EQUAL(mx1, mx2);
+ mx1 = (std::numeric_limits<Num>::max)() - 1;
+ ++mx1;
+ mx2 = (std::numeric_limits<Num>::max)();
+ BOOST_CHECK_EQUAL(mx1, mx2);
+
+ if(!std::numeric_limits<Real>::is_bounded || (std::numeric_limits<Real>::digits > std::numeric_limits<Num>::digits))
+ {
+ Real mx3((std::numeric_limits<Num>::min)() + 1);
+ --mx3;
+ Real mx4((std::numeric_limits<Num>::min)());
+ BOOST_CHECK_EQUAL(mx3, mx4);
+ mx3 = (std::numeric_limits<Num>::min)() + 1;
+ --mx3;
+ mx4 = (std::numeric_limits<Num>::min)();
+ BOOST_CHECK_EQUAL(mx3, mx4);
+ }
+ }
+}
+template <class Real, class Num>
+void test_negative_mixed_minmax(boost::mpl::false_ const&)
+{
+}
+
+template <class Real, class Num>
 void test_negative_mixed(boost::mpl::true_ const&)
 {
    typedef typename lexical_cast_target_type<Num>::type target_type;
@@ -1111,6 +1143,10 @@
    BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
    d = b * static_cast<cast_type>(n3) - static_cast<cast_type>(n1);
    BOOST_CHECK_EQUAL(d , -3 * -4 - -2);
+ //
+ // Conversion from min and max values:
+ //
+ test_negative_mixed_minmax<Real, Num>(boost::mpl::bool_<std::numeric_limits<Real>::is_integer && std::numeric_limits<Num>::is_integer>());
 }
 
 template <class Real, class Num>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk