Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86262 - in trunk/boost/multiprecision: . cpp_int
From: john_at_[hidden]
Date: 2013-10-12 08:02:11


Author: johnmaddock
Date: 2013-10-12 08:02:11 EDT (Sat, 12 Oct 2013)
New Revision: 86262
URL: http://svn.boost.org/trac/boost/changeset/86262

Log:
Use memcpy in more places.
Add optimized bitwise operations for unsigned integers.
Fixes #9243.
Refs #9231.

Text files modified:
   trunk/boost/multiprecision/cpp_int.hpp | 36 +++-----------------
   trunk/boost/multiprecision/cpp_int/bitwise.hpp | 70 +++++++++++++++++++++++++++++++++++++--
   2 files changed, 72 insertions(+), 34 deletions(-)

Modified: trunk/boost/multiprecision/cpp_int.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int.hpp Sat Oct 12 06:32:40 2013 (r86261)
+++ trunk/boost/multiprecision/cpp_int.hpp 2013-10-12 08:02:11 EDT (Sat, 12 Oct 2013) (r86262)
@@ -255,11 +255,7 @@
          // Allocate a new buffer and copy everything over:
          cap = (std::min)((std::max)(cap * 4, new_size), max_limbs);
          limb_pointer pl = allocator().allocate(cap);
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
- std::copy(limbs(), limbs() + size(), stdext::checked_array_iterator<limb_pointer>(pl, cap));
-#else
- std::copy(limbs(), limbs() + size(), pl);
-#endif
+ std::memcpy(pl, limbs(), size() * sizeof(limbs()[0]));
          if(!m_internal)
             allocator().deallocate(limbs(), capacity());
          else
@@ -282,11 +278,7 @@
    BOOST_MP_FORCEINLINE cpp_int_base(const cpp_int_base& o) : allocator_type(o), m_limbs(0), m_internal(true)
    {
       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
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
       m_sign = o.m_sign;
    }
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
@@ -295,11 +287,7 @@
    {
       if(m_internal)
       {
-#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
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
       }
       else
       {
@@ -318,11 +306,7 @@
       m_internal = o.m_internal;
       if(m_internal)
       {
-#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
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
       }
       else
       {
@@ -345,11 +329,7 @@
          static_cast<allocator_type&>(*this) = static_cast<const allocator_type&>(o);
          m_limbs = 0;
          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
+ std::memcpy(limbs(), o.limbs(), o.size() * sizeof(limbs()[0]));
          m_sign = o.m_sign;
       }
    }
@@ -1092,11 +1072,7 @@
    {
       // regular non-trivial to non-trivial assign:
       this->resize(other.size(), other.size());
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
- std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), stdext::checked_array_iterator<limb_pointer>(this->limbs(), this->size()));
-#else
- std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), this->limbs());
-#endif
+ std::memcpy(this->limbs(), other.limbs(), (std::min)(other.size(), this->size()) * sizeof(this->limbs()[0]));
       this->sign(other.sign());
       this->normalize();
    }

Modified: trunk/boost/multiprecision/cpp_int/bitwise.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int/bitwise.hpp Sat Oct 12 06:32:40 2013 (r86261)
+++ trunk/boost/multiprecision/cpp_int/bitwise.hpp 2013-10-12 08:02:11 EDT (Sat, 12 Oct 2013) (r86262)
@@ -28,7 +28,7 @@
 void bitwise_op(
    CppInt1& result,
    const CppInt2& o,
- Op op) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value))
+ Op op, const mpl::true_&) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value))
 {
    //
    // There are 4 cases:
@@ -158,6 +158,35 @@
    result.normalize();
 }
 
+template <class CppInt1, class CppInt2, class Op>
+void bitwise_op(
+ CppInt1& result,
+ const CppInt2& o,
+ Op op, const mpl::false_&) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value))
+{
+ //
+ // Both arguments are unsigned types, very simple case handled as a special case.
+ //
+ // First figure out how big the result needs to be and set up some data:
+ //
+ unsigned rs = result.size();
+ unsigned os = o.size();
+ unsigned m, x;
+ minmax(rs, os, m, x);
+ result.resize(x, x);
+ typename CppInt1::limb_pointer pr = result.limbs();
+ typename CppInt2::const_limb_pointer po = o.limbs();
+ for(unsigned i = rs; i < x; ++i)
+ pr[i] = 0;
+
+ for(unsigned i = 0; i < os; ++i)
+ pr[i] = op(pr[i], po[i]);
+ for(unsigned i = os; i < x; ++i)
+ pr[i] = op(pr[i], limb_type(0));
+
+ result.normalize();
+}
+
 struct bit_and{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a & b; } };
 struct bit_or { limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a | b; } };
 struct bit_xor{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a ^ b; } };
@@ -168,7 +197,8 @@
       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
 {
- bitwise_op(result, o, bit_and());
+ bitwise_op(result, o, bit_and(),
+ mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>());
 }
 
 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>
@@ -177,7 +207,8 @@
       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
 {
- bitwise_op(result, o, bit_or());
+ bitwise_op(result, o, bit_or(),
+ mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>());
 }
 
 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>
@@ -186,7 +217,38 @@
       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
 {
- bitwise_op(result, o, bit_xor());
+ bitwise_op(result, o, bit_xor(),
+ mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>());
+}
+//
+// Again for operands which are single limbs:
+//
+template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+ eval_bitwise_and(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ limb_type l) BOOST_NOEXCEPT
+{
+ result.limbs()[0] &= l;
+ result.resize(1, 1);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+ eval_bitwise_or(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ limb_type l) BOOST_NOEXCEPT
+{
+ result.limbs()[0] |= l;
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+ eval_bitwise_xor(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ limb_type l) BOOST_NOEXCEPT
+{
+ result.limbs()[0] ^= l;
 }
 
 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-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