|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r86258 - in trunk/boost/multiprecision: . detail
From: john_at_[hidden]
Date: 2013-10-12 04:19:30
Author: johnmaddock
Date: 2013-10-12 04:19:29 EDT (Sat, 12 Oct 2013)
New Revision: 86258
URL: http://svn.boost.org/trac/boost/changeset/86258
Log:
Optimize copying of allocator-free cpp_int's via memcpy.
Fix consistency of checks for exponents < 0 in powm.
Fixes #9231.
Refs #9236.
Text files modified:
trunk/boost/multiprecision/cpp_int.hpp | 16 ++++------------
trunk/boost/multiprecision/detail/integer_ops.hpp | 18 ++++++++++++++++++
trunk/boost/multiprecision/integer.hpp | 13 ++++++++++++-
3 files changed, 34 insertions(+), 13 deletions(-)
Modified: trunk/boost/multiprecision/cpp_int.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int.hpp Sat Oct 12 03:14:28 2013 (r86257)
+++ trunk/boost/multiprecision/cpp_int.hpp 2013-10-12 04:19:29 EDT (Sat, 12 Oct 2013) (r86258)
@@ -506,12 +506,8 @@
{
if(this != &o)
{
- resize(o.size(), o.size());
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
- std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
-#else
- std::copy(o.limbs(), o.limbs() + o.size(), limbs());
-#endif
+ m_limbs = o.m_limbs;
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(o.limbs()[0]));
m_sign = o.m_sign;
}
}
@@ -643,12 +639,8 @@
{
if(this != &o)
{
- resize(o.size(), o.size());
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
- std::copy(o.limbs(), o.limbs() + o.size(), stdext::checked_array_iterator<limb_pointer>(limbs(), size()));
-#else
- std::copy(o.limbs(), o.limbs() + o.size(), limbs());
-#endif
+ m_limbs = o.m_limbs;
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
}
}
private:
Modified: trunk/boost/multiprecision/detail/integer_ops.hpp
==============================================================================
--- trunk/boost/multiprecision/detail/integer_ops.hpp Sat Oct 12 03:14:28 2013 (r86257)
+++ trunk/boost/multiprecision/detail/integer_ops.hpp 2013-10-12 04:19:29 EDT (Sat, 12 Oct 2013) (r86258)
@@ -270,6 +270,20 @@
};
//
+// If the exponent is a signed integer type, then we need to
+// check the value is positive:
+//
+template <class Backend>
+inline void check_sign_of_backend(const Backend& v, const mpl::true_)
+{
+ if(eval_get_sign(v) < 0)
+ {
+ BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ }
+}
+template <class Backend>
+inline void check_sign_of_backend(const Backend&, const mpl::false_){}
+//
// Calculate (a^p)%c:
//
template <class Backend>
@@ -283,6 +297,8 @@
typedef typename double_precision_type<Backend>::type double_type;
typedef typename boost::multiprecision::detail::canonical<unsigned char, double_type>::type ui_type;
+
+ check_sign_of_backend(p, mpl::bool_<std::numeric_limits<number<Backend> >::is_signed>());
double_type x, y(a), b(p), t;
x = ui_type(1u);
@@ -316,6 +332,8 @@
using default_ops::eval_modulus;
using default_ops::eval_right_shift;
+ check_sign_of_backend(p, mpl::bool_<std::numeric_limits<number<Backend> >::is_signed>());
+
if(eval_get_sign(p) < 0)
{
BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
Modified: trunk/boost/multiprecision/integer.hpp
==============================================================================
--- trunk/boost/multiprecision/integer.hpp Sat Oct 12 03:14:28 2013 (r86257)
+++ trunk/boost/multiprecision/integer.hpp 2013-10-12 04:19:29 EDT (Sat, 12 Oct 2013) (r86258)
@@ -79,7 +79,7 @@
}
template <class I1, class I2, class I3>
-typename enable_if_c<is_integral<I1>::value && is_integral<I2>::value && is_integral<I3>::value, I1>::type
+typename enable_if_c<is_integral<I1>::value && is_unsigned<I2>::value && is_integral<I3>::value, I1>::type
powm(const I1& a, I2 b, I3 c)
{
typedef typename detail::double_integer<I1>::type double_type;
@@ -101,6 +101,17 @@
return x % c;
}
+template <class I1, class I2, class I3>
+inline typename enable_if_c<is_integral<I1>::value && is_signed<I2>::value && is_integral<I3>::value, I1>::type
+ powm(const I1& a, I2 b, I3 c)
+{
+ if(b < 0)
+ {
+ BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ }
+ return powm(a, static_cast<typename make_unsigned<I2>::type>(b), c);
+}
+
template <class Integer>
typename enable_if_c<is_integral<Integer>::value, unsigned>::type lsb(const Integer& val)
{
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