Boost logo

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