Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r83227 - in trunk: boost/multiprecision boost/multiprecision/cpp_int boost/multiprecision/detail libs/multiprecision/test
From: john_at_[hidden]
Date: 2013-03-01 08:15:57


Author: johnmaddock
Date: 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
New Revision: 83227
URL: http://svn.boost.org/trac/boost/changeset/83227

Log:
Fix operators that operate on unary-negated expressions.
Suppress some MSVC specific warnings.
Fix some bugs exposed by above changes and add new test cases.
Fixes #8176.
Text files modified:
   trunk/boost/multiprecision/cpp_int/comparison.hpp | 13 ++++++++++++
   trunk/boost/multiprecision/debug_adaptor.hpp | 4 +-
   trunk/boost/multiprecision/detail/et_ops.hpp | 42 ++++++++++++++++++++--------------------
   trunk/boost/multiprecision/detail/number_base.hpp | 1
   trunk/boost/multiprecision/logged_adaptor.hpp | 4 +-
   trunk/boost/multiprecision/number.hpp | 12 +++++-----
   trunk/libs/multiprecision/test/test_mixed_cpp_int.cpp | 29 +++++++++++++++++++++++++++
   7 files changed, 74 insertions(+), 31 deletions(-)

Modified: trunk/boost/multiprecision/cpp_int/comparison.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int/comparison.hpp (original)
+++ trunk/boost/multiprecision/cpp_int/comparison.hpp 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
@@ -27,9 +27,16 @@
>::type
    eval_eq(const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& a, const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& b) BOOST_NOEXCEPT
 {
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+ return (a.sign() == b.sign())
+ && (a.size() == b.size())
+ && std::equal(a.limbs(), a.limbs() + a.size(),
+ stdext::checked_array_iterator<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::const_limb_pointer>(b.limbs(), b.size()));
+#else
    return (a.sign() == b.sign())
       && (a.size() == b.size())
       && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs());
+#endif
 }
 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
 BOOST_MP_FORCEINLINE typename enable_if_c<
@@ -39,9 +46,15 @@
>::type
    eval_eq(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b) BOOST_NOEXCEPT
 {
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+ return (a.sign() == b.sign())
+ && (a.size() == b.size())
+ && std::equal(a.limbs(), a.limbs() + a.size(), stdext::checked_array_iterator<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer>(b.limbs(), b.size()));
+#else
    return (a.sign() == b.sign())
       && (a.size() == b.size())
       && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs());
+#endif
 }
 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
 BOOST_MP_FORCEINLINE typename enable_if_c<

Modified: trunk/boost/multiprecision/debug_adaptor.hpp
==============================================================================
--- trunk/boost/multiprecision/debug_adaptor.hpp (original)
+++ trunk/boost/multiprecision/debug_adaptor.hpp 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
@@ -303,7 +303,7 @@
 inline void eval_left_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
 {
    using default_ops::eval_left_shift;
- eval_left_shift(arg.value(), a, b);
+ eval_left_shift(arg.value(), a.value(), b);
    arg.update_view();\
 }
 template <class Backend>
@@ -317,7 +317,7 @@
 inline void eval_right_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
 {
    using default_ops::eval_right_shift;
- eval_right_shift(arg.value(), a, b);
+ eval_right_shift(arg.value(), a.value(), b);
    arg.update_view();\
 }
 

Modified: trunk/boost/multiprecision/detail/et_ops.hpp
==============================================================================
--- trunk/boost/multiprecision/detail/et_ops.hpp (original)
+++ trunk/boost/multiprecision/detail/et_ops.hpp 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
@@ -148,16 +148,16 @@
 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
 //
 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
+inline detail::expression<detail::minus, number<B, ET>, Arg1>
    operator + (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
 {
- return detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref());
+ return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
 }
 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
+inline detail::expression<detail::minus, number<B, ET>, Arg1>
    operator + (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
 {
- return detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref());
+ return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
 }
 template <class B>
 inline detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
@@ -250,17 +250,17 @@
 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
 //
 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
+inline detail::expression<detail::plus, number<B, ET>, Arg1>
    operator - (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
 {
- return detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref());
+ return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
 }
 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+inline detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
    operator - (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
 {
- return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref()));
+ return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
+ detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
 }
 template <class B>
 inline detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
@@ -354,18 +354,18 @@
 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
 //
 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
    operator * (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
 {
- return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > (a, b.left_ref()));
+ return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
+ detail::expression<detail::multiplies, number<B, ET>, Arg1> (a, b.left_ref()));
 }
 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
    operator * (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
 {
- return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref()));
+ return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
+ detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
 }
 template <class B>
 inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
@@ -464,18 +464,18 @@
 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
 //
 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+inline detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
    operator / (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
 {
- return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::divides, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref()));
+ return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
+ detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
 }
 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
-inline detail::expression<detail::negate, detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, ET> > >
+inline detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
    operator / (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
 {
- return detail::expression<detail::negate, detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, ET> > >(
- detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, ET> >(a.left_ref(), b));
+ return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
+ detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
 }
 template <class B>
 inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >

Modified: trunk/boost/multiprecision/detail/number_base.hpp
==============================================================================
--- trunk/boost/multiprecision/detail/number_base.hpp (original)
+++ trunk/boost/multiprecision/detail/number_base.hpp 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
@@ -319,6 +319,7 @@
 {
    typedef mpl::int_<1> arity;
    typedef typename arg_type<Arg1>::type left_type;
+ typedef typename left_type::result_type left_result_type;
    typedef typename left_type::result_type result_type;
    typedef tag tag_type;
 

Modified: trunk/boost/multiprecision/logged_adaptor.hpp
==============================================================================
--- trunk/boost/multiprecision/logged_adaptor.hpp (original)
+++ trunk/boost/multiprecision/logged_adaptor.hpp 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
@@ -343,7 +343,7 @@
 {
    using default_ops::eval_left_shift;
    log_prefix_event(arg.value(), a, b, "<<");
- eval_left_shift(arg.value(), a, b);
+ eval_left_shift(arg.value(), a.value(), b);
    log_postfix_event(arg.value(), "<<");
 }
 template <class Backend>
@@ -359,7 +359,7 @@
 {
    using default_ops::eval_right_shift;
    log_prefix_event(arg.value(), a, b, ">>");
- eval_right_shift(arg.value(), a, b);
+ eval_right_shift(arg.value(), a.value(), b);
    log_postfix_event(arg.value(), ">>");
 }
 

Modified: trunk/boost/multiprecision/number.hpp
==============================================================================
--- trunk/boost/multiprecision/number.hpp (original)
+++ trunk/boost/multiprecision/number.hpp 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
@@ -392,7 +392,7 @@
    {
       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::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))>(), is_signed<V>());
- eval_left_shift(m_backend, canonical_value(val));
+ eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
       return *this;
    }
 
@@ -401,7 +401,7 @@
    {
       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::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))>(), is_signed<V>());
- eval_right_shift(m_backend, canonical_value(val));
+ eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
       return *this;
    }
 
@@ -1114,7 +1114,7 @@
       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
       using default_ops::eval_right_shift;
       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
- eval_right_shift(m_backend, canonical_value(e.value()), val);
+ eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
    }
 
    template <class Exp, class Val>
@@ -1123,7 +1123,7 @@
       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
       using default_ops::eval_left_shift;
       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
- eval_left_shift(m_backend, canonical_value(e.value()), val);
+ eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
    }
 
    template <class Exp, class Val, class Tag>
@@ -1133,7 +1133,7 @@
       using default_ops::eval_right_shift;
       self_type temp(e);
       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
- eval_right_shift(m_backend, temp.backend(), val);
+ eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
    }
 
    template <class Exp, class Val, class Tag>
@@ -1143,7 +1143,7 @@
       using default_ops::eval_left_shift;
       self_type temp(e);
       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
- eval_left_shift(m_backend, temp.backend(), val);
+ eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
    }
 
    template <class Exp>

Modified: trunk/libs/multiprecision/test/test_mixed_cpp_int.cpp
==============================================================================
--- trunk/libs/multiprecision/test/test_mixed_cpp_int.cpp (original)
+++ trunk/libs/multiprecision/test/test_mixed_cpp_int.cpp 2013-03-01 08:15:56 EST (Fri, 01 Mar 2013)
@@ -69,10 +69,39 @@
    }
 }
 
+void test_rational_mixed()
+{
+ using namespace boost::multiprecision;
+ cpp_int a(2);
+ cpp_rational r(10);
+
+ BOOST_CHECK_EQUAL(a + -r, -8);
+ BOOST_CHECK_EQUAL(-r + a, -8);
+ BOOST_CHECK_EQUAL(-a + r, 8);
+ BOOST_CHECK_EQUAL(r + -a, 8);
+
+ BOOST_CHECK_EQUAL(a - -r, 12);
+ BOOST_CHECK_EQUAL(-r - a, -12);
+ BOOST_CHECK_EQUAL(-a - r, -12);
+ BOOST_CHECK_EQUAL(r - -a, 12);
+
+ BOOST_CHECK_EQUAL(a * -r, -20);
+ BOOST_CHECK_EQUAL(-r * a, -20);
+ BOOST_CHECK_EQUAL(-a * r, -20);
+ BOOST_CHECK_EQUAL(r * -a, -20);
+
+ BOOST_CHECK_EQUAL(a / -r, cpp_rational(-2, 10));
+ BOOST_CHECK_EQUAL(-r / a, -5);
+ BOOST_CHECK_EQUAL(cpp_rational(-a / r), cpp_rational(-2, 10));
+ BOOST_CHECK_EQUAL(r / -a, -5);
+}
+
 int main()
 {
    using namespace boost::multiprecision;
 
+ test_rational_mixed();
+
    test<checked_int512_t, checked_int1024_t>();
    test<checked_int256_t, checked_int512_t>();
    test<number<cpp_int_backend<64, 64, signed_magnitude, checked, void>, et_off>, checked_int128_t>();


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