|
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