Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r50541 - in sandbox/mp_math: . boost/mp_math/mp_int boost/mp_math/mp_int/detail libs/mp_math/test libs/mp_math/tools/benchmark
From: baraclese_at_[hidden]
Date: 2009-01-10 19:30:29


Author: baraclese
Date: 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
New Revision: 50541
URL: http://svn.boost.org/trac/boost/changeset/50541

Log:
* mp_int/ctors.hpp
  Ctors now have an allocator reference parameter.
  Fixed a bug in dtor reported by Nathan Kitchen on Boost devel mailing list on 10th January.
* mp_int/sqr.hpp
  Added small optimization to comba_sqr().
* mp_int/detail/primitive_ops.hpp
  Added multiply_by_two, divide_by_two and divide_by_digit functions.
* mp_int/detail/integral_ops.hpp
  Added parenthesis around expression to calculate q constant, reported by Nathan Kitchen.
* mp_int/div.hpp
  Moved division algo to detail/div.hpp and renamed function to classic_divide.
* mp_int/detail/div.hpp
  New.
* mp_int/root.hpp
  Fixed nth_root. Added better initial approximation for Newton method.
* mp_int/mp_int.hpp
  Added clamp_high_digit().
  Added clear_bit, set_bits, clear_bits, truncate functions.
  Removed is_zero().
  Removed divide().
  Fixed deallocate() null ptr bug as reported by Nathan Kitchen.
* test/bitmanipulation.cpp
  New file to test set_bit, clear_bit functions.

Added:
   sandbox/mp_math/boost/mp_math/mp_int/detail/div.hpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/bitmanipulation.cpp (contents, props changed)
Text files modified:
   sandbox/mp_math/boost/mp_math/mp_int/add.hpp | 7
   sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp | 46 +++++-
   sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp | 45 +++---
   sandbox/mp_math/boost/mp_math/mp_int/detail/modular_reduction.hpp | 6
   sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp | 262 +++++++++++++++++++++++++++++----------
   sandbox/mp_math/boost/mp_math/mp_int/div.hpp | 223 ++++-----------------------------
   sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp | 2
   sandbox/mp_math/boost/mp_math/mp_int/mod.hpp | 3
   sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp | 173 ++++++++++++++++++++------
   sandbox/mp_math/boost/mp_math/mp_int/mul.hpp | 33 +---
   sandbox/mp_math/boost/mp_math/mp_int/operators.hpp | 24 +-
   sandbox/mp_math/boost/mp_math/mp_int/root.hpp | 53 +++++--
   sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp | 34 ++++-
   sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp | 39 +++--
   sandbox/mp_math/libs/mp_math/test/cmp.cpp | 6
   sandbox/mp_math/libs/mp_math/test/ctors.cpp | 4
   sandbox/mp_math/libs/mp_math/test/div.cpp | 16 ++
   sandbox/mp_math/libs/mp_math/test/integral_ops.cpp | 17 ++
   sandbox/mp_math/libs/mp_math/test/jamfile.v2 | 19 +-
   sandbox/mp_math/libs/mp_math/test/root.cpp | 14 ++
   sandbox/mp_math/libs/mp_math/test/shift.cpp | 7 +
   sandbox/mp_math/libs/mp_math/test/string_ops.cpp | 2
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp | 2
   sandbox/mp_math/project-root.jam | 2
   24 files changed, 603 insertions(+), 436 deletions(-)

Modified: sandbox/mp_math/boost/mp_math/mp_int/add.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/add.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/add.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -19,7 +19,7 @@
     if (digits_[0] >= b) // example: -16 + 5 = -11; or -5 + 5 = 0
     {
       digits_[0] -= b;
- if (is_zero())
+ if (!*this)
         set_sign(1);
     }
     else
@@ -77,10 +77,7 @@
     return;
   }
   else if (carry) // at this point n equals x->size_
- {
- digits_[n] = carry;
- ++n;
- }
+ digits_[n++] = carry;
 
   size_ = n;
 }

Modified: sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -1,4 +1,4 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -13,11 +13,23 @@
 }
 
 template<class A, class T>
+mp_int<A,T>::mp_int(const allocator_type& a)
+:
+ base_allocator_type(a),
+ digits_(0),
+ size_(0),
+ capacity_(0)
+{
+}
+
+template<class A, class T>
 template<typename IntegralT>
 mp_int<A,T>::mp_int(
     IntegralT b,
+ const allocator_type& a,
     typename enable_if<is_integral<IntegralT> >::type*)
 :
+ base_allocator_type(a),
   digits_(0),
   size_(0),
   capacity_(0)
@@ -50,10 +62,10 @@
       ++c;
     sign = 1;
   }
-
+
   // detect the radix
   unsigned int radix;
-
+
   if (c != last)
   {
     if (*c == '0') // octal
@@ -111,7 +123,7 @@
     }
     set_sign(1);
   }
-
+
   const bool uppercase = f & std::ios_base::uppercase;
   const bool showbase = f & std::ios_base::showbase;
 
@@ -158,8 +170,11 @@
 
 template<class A, class T>
 template<typename RandomAccessIterator>
-mp_int<A,T>::mp_int(RandomAccessIterator first, RandomAccessIterator last)
+mp_int<A,T>::mp_int(RandomAccessIterator first,
+ RandomAccessIterator last,
+ const allocator_type& a)
 :
+ base_allocator_type(a),
   digits_(0),
   size_(0),
   capacity_(0)
@@ -169,8 +184,9 @@
 
 template<class A, class T>
 template<typename charT>
-mp_int<A,T>::mp_int(const charT* s)
+mp_int<A,T>::mp_int(const charT* s, const allocator_type& a)
 :
+ base_allocator_type(a),
   digits_(0),
   size_(0),
   capacity_(0)
@@ -180,8 +196,11 @@
 
 template<class A, class T>
 template<typename charT>
-mp_int<A,T>::mp_int(const charT* s, std::ios_base::fmtflags f)
+mp_int<A,T>::mp_int(const charT* s,
+ std::ios_base::fmtflags f,
+ const allocator_type& a)
 :
+ base_allocator_type(a),
   digits_(0),
   size_(0),
   capacity_(0)
@@ -191,8 +210,10 @@
 
 template<class A, class T>
 template<typename charT, class traits, class Alloc>
-mp_int<A,T>::mp_int(const std::basic_string<charT,traits,Alloc>& s)
+mp_int<A,T>::mp_int(const std::basic_string<charT,traits,Alloc>& s,
+ const allocator_type& a)
 :
+ base_allocator_type(a),
   digits_(0),
   size_(0),
   capacity_(0)
@@ -203,8 +224,10 @@
 template<class A, class T>
 template<typename charT, class traits, class Alloc>
 mp_int<A,T>::mp_int(const std::basic_string<charT,traits,Alloc>& s,
- std::ios_base::fmtflags f)
+ std::ios_base::fmtflags f,
+ const allocator_type& a)
 :
+ base_allocator_type(a),
   digits_(0),
   size_(0),
   capacity_(0)
@@ -215,6 +238,8 @@
 
 template<class A, class T>
 mp_int<A,T>::mp_int(const mp_int& copy)
+:
+ base_allocator_type(copy.get_allocator())
 {
   digits_ = this->allocate(copy.size_);
   std::memcpy(digits_, copy.digits_, copy.size_ * sizeof(digit_type));
@@ -241,6 +266,7 @@
 template<class A, class T>
 mp_int<A,T>::~mp_int()
 {
- this->deallocate(digits_, capacity());
+ if (digits_)
+ this->deallocate(digits_, capacity());
 }
 

Added: sandbox/mp_math/boost/mp_math/mp_int/detail/div.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/div.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -0,0 +1,174 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_DETAIL_DIV_HPP
+#define BOOST_MP_MATH_MP_INT_DETAIL_DIV_HPP
+
+#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+// integer signed division.
+// q*b + r == a
+// HAC pp.598 Algorithm 14.20
+//
+// Note that the description in HAC is horribly incomplete. For example, it
+// doesn't consider the case where digits are removed from 'x' in the inner
+// loop. It also doesn't consider the case that y has fewer than three digits,
+// etc..
+// The overall algorithm is as described as 14.20 from HAC but fixed to treat
+// these cases.
+
+// divide a by b, optionally store remainder
+template<class A, class T>
+void classic_divide(const mp_int<A,T>& a, const mp_int<A,T>& b,
+ mp_int<A,T>& q, mp_int<A,T>* remainder = 0)
+{
+ typedef typename mp_int<A,T>::digit_type digit_type;
+ typedef typename mp_int<A,T>::word_type word_type;
+ typedef typename mp_int<A,T>::size_type size_type;
+
+ if (!b)
+ throw std::domain_error("mp_int::divide: division by zero");
+
+ // if *this < b then q=0, r = *this
+ if (a.compare_magnitude(b) == -1)
+ {
+ if (remainder)
+ *remainder = a;
+ q.zero();
+ return;
+ }
+
+ q.grow_capacity(a.size() + 2);
+ q.set_size(a.size() + 2);
+ std::memset(q.digits(), 0, q.size() * sizeof(digit_type));
+
+ mp_int<A,T> x(a);
+ mp_int<A,T> y(b);
+
+ // fix the sign
+ const int neg = (a.sign() == b.sign()) ? 1 : -1;
+ x.set_sign(1);
+ y.set_sign(1);
+
+ // normalize both x and y, ensure that y >= beta/2, [beta == 2**valid_bits]
+ size_type norm = y.precision() % mp_int<A,T>::valid_bits;
+ if (norm < mp_int<A,T>::valid_bits - 1)
+ {
+ norm = mp_int<A,T>::valid_bits - 1 - norm;
+ x <<= norm;
+ y <<= norm;
+ }
+ else
+ norm = 0;
+
+ // note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4
+ const size_type n = x.size() - 1;
+ const size_type t = y.size() - 1;
+
+ // find leading digit of the quotient
+ // while (x >= y*beta**(n-t)) do { q[n-t] += 1; x -= y*beta**(n-t) }
+ y.shift_digits_left(n - t); // y = y*beta**(n-t)
+
+ while (x.compare(y) != -1)
+ {
+ ++q[n - t];
+ x -= y;
+ }
+
+ // reset y by shifting it back down
+ y.shift_digits_right(n - t);
+
+ // find the remainder of the digits
+ // step 3. for i from n down to (t + 1)
+ for (size_type i = n; i >= (t + 1); --i)
+ {
+ if (i > x.size())
+ continue;
+
+ // step 3.1 if xi == yt then set q{i-t-1} to beta-1,
+ // otherwise set q{i-t-1} to (xi*beta + x{i-1})/yt
+ if (x[i] == y[t])
+ q[i - t - 1] = mp_int<A,T>::digit_max;
+ else
+ {
+ word_type tmp = static_cast<word_type>(x[i])
+ << static_cast<word_type>(mp_int<A,T>::valid_bits);
+ tmp |= x[i - 1];
+ tmp /= y[t];
+ q[i - t - 1] = static_cast<digit_type>(tmp);
+ }
+
+ // now fixup quotient estimation
+ // while (q{i-t-1} * (yt * beta + y{t-1})) >
+ // xi * beta**2 + xi-1 * beta + xi-2
+ //
+ // do q{i-t-1} -= 1;
+
+ mp_int<A,T> t1, t2;
+ t1.grow_capacity(3);
+ t2.grow_capacity(3);
+
+ ++q[i - t - 1];
+ do
+ {
+ --q[i - t - 1];
+
+ // find left hand
+ t1.zero();
+ t1[0] = (t == 0) ? 0 : y[t - 1];
+ t1[1] = y[t];
+ t1.set_size(2);
+ t1.multiply_by_digit(q[i - t - 1]);
+
+ // find right hand
+ t2[0] = (i < 2) ? 0 : x[i - 2];
+ t2[1] = (i == 0) ? 0 : x[i - 1];
+ t2[2] = x[i];
+ t2.set_size(3);
+ } while (t1.compare_magnitude(t2) == 1);
+
+ // step 3.3 x = x - q{i-t-1} * y * beta**{i-t-1}
+ t1 = y;
+ t1.multiply_by_digit(q[i - t -1]);
+ t1.shift_digits_left(i - t - 1);
+ x -= t1;
+
+ // if x < 0 then { x = x + y*beta**{i-t-1}; q{i-t-1} -= 1; }
+ if (x.is_negative())
+ {
+ t1 = y;
+ t1.shift_digits_left(i - t -1);
+ x += t1;
+
+ --q[i - t - 1] = q[i - t - 1];
+ }
+ }
+
+ // now q is the quotient and x is the remainder [which we have to normalize]
+
+ // get sign before writing to q
+ x.set_sign(!x ? 1 : a.sign());
+
+ q.clamp();
+ q.set_sign(neg);
+
+ if (remainder)
+ {
+ x >>= norm;
+ remainder->swap(x);
+ }
+}
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Modified: sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -1,4 +1,4 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -42,7 +42,7 @@
 
   static bool equal (const MpInt& lhs, IntegralT rhs);
   static bool less (const MpInt& lhs, IntegralT rhs);
-
+
   static void add (MpInt& lhs, IntegralT rhs);
   static void subtract(MpInt& lhs, IntegralT rhs);
   static void multiply(MpInt& lhs, IntegralT rhs);
@@ -82,7 +82,7 @@
 
   static bool equal (const MpInt& lhs, IntegralT rhs);
   static bool less (const MpInt& lhs, IntegralT rhs);
-
+
   static void add (MpInt& lhs, IntegralT rhs);
   static void subtract(MpInt& lhs, IntegralT rhs);
   static void multiply(MpInt& lhs, IntegralT rhs);
@@ -98,7 +98,7 @@
   typedef typename make_unsigned<IntegralT>::type unsigned_type;
 
   static const typename MpInt::size_type q =
- std::numeric_limits<IntegralT>::digits + (MpInt::valid_bits - 1)
+ (std::numeric_limits<IntegralT>::digits + (MpInt::valid_bits - 1))
     / MpInt::valid_bits;
 
   static bool equal_to_integral_type(const MpInt& x, IntegralT y)
@@ -121,12 +121,13 @@
 integral_ops_impl<IntegralT, MpInt, false>::assign(MpInt& lhs, IntegralT rhs)
 {
   lhs.zero();
-
+
+ typedef typename MpInt::digit_type digit_type;
+
   if (rhs <= MpInt::digit_max)
- lhs[0] = rhs;
+ lhs[0] = static_cast<digit_type>(rhs);
   else
   {
- typedef typename MpInt::digit_type digit_type;
     static const int ud = std::numeric_limits<IntegralT>::digits;
     static const int dd = MpInt::valid_bits;
     static const int m = dd < ud ? dd : ud;
@@ -181,7 +182,7 @@
 {
   if (lhs.size() > q)
     return false;
-
+
   return equal_to_integral_type(lhs, rhs);
 }
 
@@ -190,7 +191,7 @@
 integral_ops_impl<IntegralT, MpInt, true>::equal(const MpInt& lhs, IntegralT rhs)
 {
   const int r_sign = rhs < 0 ? -1 : 1;
-
+
   if (lhs.sign() != r_sign)
     return false;
 
@@ -219,7 +220,7 @@
 {
   if (lhs.sign() == -1 && rhs >= 0)
     return true;
-
+
   if (lhs.sign() == 1 && rhs < 0)
     return false;
 
@@ -414,7 +415,7 @@
 integral_ops_impl<IntegralT, MpInt, false>::bitwise_or(MpInt& lhs, IntegralT rhs)
 {
   if (rhs <= MpInt::digit_max)
- lhs[0] |= rhs;
+ lhs[0] |= static_cast<typename MpInt::digit_type>(rhs);
   else
     lhs |= MpInt(rhs);
 }
@@ -441,7 +442,7 @@
 integral_ops_impl<IntegralT, MpInt, false>::bitwise_and(MpInt& lhs, IntegralT rhs)
 {
   if (rhs <= MpInt::digit_max)
- lhs[0] &= rhs;
+ lhs[0] &= static_cast<typename MpInt::digit_type>(rhs);
   else
     lhs &= MpInt(rhs);
 }
@@ -467,7 +468,7 @@
 integral_ops_impl<IntegralT, MpInt, false>::bitwise_xor(MpInt& lhs, IntegralT rhs)
 {
   if (rhs <= MpInt::digit_max)
- lhs[0] ^= rhs;
+ lhs[0] ^= static_cast<typename MpInt::digit_type>(rhs);
   else
     lhs ^= MpInt(rhs);
 }
@@ -507,7 +508,7 @@
 {
   typedef std::numeric_limits<IntegralT> integral_type_limits;
   typedef typename make_unsigned<IntegralT>::type unsigned_type;
-
+
   static IntegralT to_integral(const MpInt& x);
 };
 
@@ -516,7 +517,7 @@
 {
   typedef std::numeric_limits<IntegralT> integral_type_limits;
   typedef typename make_unsigned<IntegralT>::type unsigned_type;
-
+
   static IntegralT to_integral(const MpInt& x);
 };
 
@@ -524,7 +525,7 @@
 struct integral_ops2<IntegralT, MpInt, false, true>
 {
   typedef std::numeric_limits<IntegralT> integral_type_limits;
-
+
   static IntegralT apply_shift(const MpInt& x);
   static IntegralT to_integral(const MpInt& x);
 };
@@ -533,7 +534,7 @@
 struct integral_ops2<IntegralT, MpInt, false, false>
 {
   typedef std::numeric_limits<IntegralT> integral_type_limits;
-
+
   static IntegralT apply_shift(const MpInt& x);
   static IntegralT to_integral(const MpInt& x);
 };
@@ -572,7 +573,7 @@
 {
   int shift_count = 0;
   IntegralT tmp = 0;
-
+
   for (typename MpInt::const_reverse_iterator digit = x.rbegin();
       digit != x.rend(); ++digit)
   {
@@ -597,7 +598,7 @@
   else
     throw std::overflow_error(
         "to_integral: cannot convert negative number to unsigned integral type");
-
+
   return apply_shift(x);
 }
 
@@ -631,13 +632,13 @@
   {
     return integral_ops2<IntegralT, mp_int<A,T> >::to_integral(x);
   }
-
+
   template<class A, class T>
   static void assign(mp_int<A,T>& lhs, IntegralT rhs)
   {
     integral_ops_impl<IntegralT, mp_int<A,T> >::assign(lhs, rhs);
   }
-
+
   template<class A, class T>
   static bool equal(const mp_int<A,T>& lhs, IntegralT rhs)
   {
@@ -667,7 +668,7 @@
   {
     integral_ops_impl<IntegralT, mp_int<A,T> >::multiply(lhs, rhs);
   }
-
+
   template<class A, class T>
   static void divide(mp_int<A,T>& lhs, IntegralT rhs)
   {

Modified: sandbox/mp_math/boost/mp_math/mp_int/detail/modular_reduction.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/detail/modular_reduction.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/modular_reduction.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -103,7 +103,8 @@
 
   // x = x/base**m.size()
   x.clamp();
- if (x.is_zero())
+
+ if (!x)
     x.set_sign(1);
 
   x.shift_digits_right(m.size());
@@ -186,7 +187,8 @@
     std::memset(x.digits() + m + 1, 0, (x.size() - (m + 1)) * sizeof(digit_type));
 
   x.clamp();
- if (x.is_zero())
+
+ if (!x)
     x.set_sign(1);
 
   if (x.compare_magnitude(n) != -1)

Modified: sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -20,17 +20,17 @@
   typedef DigitT digit_type;
   typedef WordT word_type;
   typedef SizeT size_type;
-
+
   static const word_type digit_bits = std::numeric_limits<digit_type>::digits;
 
   // ADD ------------------------------------
 
- // add x to the digits in y and store result in z
- // ylen must be > 0
+ // add y to the digits in x and store result in z
+ // xlen must be > 0
   // returns: the last carry (it will not get stored in z)
   static digit_type add_single_digit(digit_type* z,
- const digit_type* y, size_type ylen,
- digit_type x);
+ const digit_type* x, size_type xlen,
+ digit_type y);
 
   // z = x + y, returns last carry
   static digit_type add_digits(digit_type* z,
@@ -56,8 +56,8 @@
 
   // subtracts x from the digits in y and store result in z
   static void subtract_single_digit(digit_type* z,
- const digit_type* y, size_type ylen,
- digit_type x);
+ const digit_type* x, size_type xlen,
+ digit_type y);
 
   // z = x - y, returns last borrow
   static digit_type subtract_digits(digit_type* z,
@@ -82,8 +82,12 @@
   // multiply y of length ylen with x and store result in z
   // returns: the last carry (it will not get stored in z)
   static digit_type multiply_by_digit(digit_type* z,
- const digit_type* y, size_type ylen,
- digit_type x);
+ const digit_type* x, size_type xlen,
+ digit_type y);
+
+ // z = x * 2
+ static digit_type multiply_by_two(digit_type* z,
+ const digit_type* x, size_type len);
 
   // z = x * y
   static void classic_mul(digit_type* z, const digit_type* x, size_type xlen,
@@ -111,24 +115,35 @@
                                         digit_type x,
                                         const digit_type* y,
                                         size_type n);
+
+ // DIV -------------------------------------
+
+ // z = x / 2
+ static void divide_by_two(digit_type* z, const digit_type* x, size_type len);
+
+ // z = x / y
+ // returns remainder
+ static digit_type divide_by_digit(digit_type* z,
+ const digit_type* x, size_type xlen,
+ digit_type y);
 };
 
 
 
 template<typename D, typename W, typename S>
 inline
-typename basic_primitive_ops<D,W,S>::digit_type
-basic_primitive_ops<D,W,S>::add_single_digit(digit_type* z,
- const digit_type* y, size_type ylen,
- digit_type x)
+D basic_primitive_ops<D,W,S>::add_single_digit(digit_type* z,
+ const digit_type* x,
+ size_type xlen,
+ digit_type y)
 {
- word_type carry = static_cast<word_type>(*y++) + x;
+ word_type carry = static_cast<word_type>(*x++) + y;
   *z++ = static_cast<digit_type>(carry);
   carry >>= digit_bits;
 
- while (carry && --ylen)
+ while (carry && --xlen)
   {
- carry += static_cast<word_type>(*y++);
+ carry += static_cast<word_type>(*x++);
     *z++ = static_cast<digit_type>(carry);
     carry >>= digit_bits;
   }
@@ -139,10 +154,9 @@
 
 template<typename D, typename W, typename S>
 inline
-typename basic_primitive_ops<D,W,S>::digit_type
-basic_primitive_ops<D,W,S>::add_digits(digit_type* z,
- const digit_type* x,
- const digit_type* y, size_type n)
+D basic_primitive_ops<D,W,S>::add_digits(digit_type* z,
+ const digit_type* x,
+ const digit_type* y, size_type n)
 {
   word_type carry = 0;
 
@@ -158,11 +172,10 @@
 
 template<typename D, typename W, typename S>
 inline
-typename basic_primitive_ops<D,W,S>::size_type
-basic_primitive_ops<D,W,S>::ripple_carry(digit_type* z,
- const digit_type* x,
- size_type n,
- digit_type& carry)
+S basic_primitive_ops<D,W,S>::ripple_carry(digit_type* z,
+ const digit_type* x,
+ size_type n,
+ digit_type& carry)
 {
   word_type c = carry;
   size_type i = 0;
@@ -175,27 +188,27 @@
   }
 
   carry = static_cast<digit_type>(c);
-
+
   return i;
 }
 
 template<typename D, typename W, typename S>
 inline
-typename basic_primitive_ops<D,W,S>::digit_type
-basic_primitive_ops<D,W,S>::add_smaller_magnitude(
- digit_type* z,
- const digit_type* x, size_type xlen,
- const digit_type* y, size_type ylen)
+D basic_primitive_ops<D,W,S>::add_smaller_magnitude(digit_type* z,
+ const digit_type* x,
+ size_type xlen,
+ const digit_type* y,
+ size_type ylen)
 {
   digit_type carry = add_digits(z, x, y, ylen);
 
   size_type n = ripple_carry(z + ylen, x + ylen, xlen - ylen, carry);
 
   n += ylen;
-
+
   if (n < xlen && z != x)
     std::memcpy(z + n, x + n, sizeof(digit_type) * (xlen - n));
-
+
   return carry;
 }
 
@@ -203,7 +216,8 @@
 inline
 void
 basic_primitive_ops<D,W,S>::subtract_single_digit(digit_type* z,
- const digit_type* y, size_type ylen,
+ const digit_type* y,
+ size_type ylen,
                                                   digit_type x)
 {
   word_type borrow = static_cast<word_type>(*y++) - x;
@@ -220,11 +234,10 @@
 
 template<typename D, typename W, typename S>
 inline
-typename basic_primitive_ops<D,W,S>::digit_type
-basic_primitive_ops<D,W,S>::subtract_digits(digit_type* z,
- const digit_type* x,
- const digit_type* y,
- size_type n)
+D basic_primitive_ops<D,W,S>::subtract_digits(digit_type* z,
+ const digit_type* x,
+ const digit_type* y,
+ size_type n)
 {
   word_type borrow = 0;
 
@@ -240,11 +253,10 @@
 
 template<typename D, typename W, typename S>
 inline
-typename basic_primitive_ops<D,W,S>::size_type
-basic_primitive_ops<D,W,S>::ripple_borrow(digit_type* z,
- const digit_type* x,
- size_type n,
- digit_type borrow)
+S basic_primitive_ops<D,W,S>::ripple_borrow(digit_type* z,
+ const digit_type* x,
+ size_type n,
+ digit_type borrow)
 {
   word_type b = borrow;
   size_type i = 0;
@@ -254,7 +266,7 @@
     *z++ = static_cast<digit_type>(b);
     b >>= std::numeric_limits<word_type>::digits - 1;
   }
-
+
   return i;
 }
 
@@ -276,13 +288,12 @@
   }
 }
 
-
 template<typename D, typename W, typename S>
 inline
-typename basic_primitive_ops<D,W,S>::digit_type
-basic_primitive_ops<D,W,S>::multiply_by_digit(digit_type* z,
- const digit_type* y, size_type ylen,
- digit_type x)
+D basic_primitive_ops<D,W,S>::multiply_by_digit(digit_type* z,
+ const digit_type* y,
+ size_type ylen,
+ digit_type x)
 {
   digit_type carry = 0;
 
@@ -294,6 +305,29 @@
     *z++ = static_cast<digit_type>(tmp);
     carry = static_cast<digit_type>(tmp >> digit_bits);
   }
+
+ return carry;
+}
+
+template<typename D, typename W, typename S>
+inline
+D basic_primitive_ops<D,W,S>::multiply_by_two(digit_type* z,
+ const digit_type* x, size_type n)
+{
+ static const digit_type one = 1U;
+
+ digit_type carry = 0;
+
+ while (n--)
+ {
+ // get carry bit for next iteration
+ const digit_type r = *x >> (static_cast<digit_type>(digit_bits) - one);
+
+ *z++ = (*x++ << one) | carry;
+
+ carry = r;
+ }
+
   return carry;
 }
 
@@ -306,7 +340,7 @@
   // phase 1
   word_type tmp = static_cast<word_type>(x[0]) * static_cast<word_type>(y[0]);
   z[0] = static_cast<digit_type>(tmp);
-
+
   for (size_type i = 1; i < xlen; ++i)
   {
     tmp = (tmp >> digit_bits)
@@ -314,10 +348,10 @@
         * static_cast<word_type>(y[0]);
     z[i] = static_cast<digit_type>(tmp);
   }
-
+
   tmp >>= digit_bits;
   z[xlen] = static_cast<digit_type>(tmp);
-
+
   // phase 2
   for (size_type i = 1; i < ylen; ++i)
   {
@@ -325,7 +359,7 @@
         * static_cast<word_type>(x[0])
         + static_cast<word_type>(z[i]);
     z[i] = static_cast<digit_type>(tmp);
-
+
     for (size_type j = 1; j < xlen; ++j)
     {
       tmp = (tmp >> digit_bits)
@@ -333,7 +367,7 @@
           + static_cast<word_type>(z[i+j]);
       z[i+j] = static_cast<digit_type>(tmp);
     }
-
+
     tmp >>= digit_bits;
     z[i + xlen] = static_cast<digit_type>(tmp);
   }
@@ -348,8 +382,8 @@
 //----------------------------------
 // | 18 15 | 12 9 6
 // 12 | 10 8 | 6 4
-// 12 10 | 8 6 | 4
-// | |
+// 12 10 | 8 6 | 4
+// | |
 // phase: 3 | 2 | 1
 //
 // TODO handle too long columns => carry may overflow. This can happen if
@@ -365,7 +399,7 @@
 
   word_type acc = 0; // accumulator for each column
   word_type carry = 0;
-
+
   // phase 1
   for (size_type i = 0; i < ylen; ++i)
   {
@@ -401,7 +435,7 @@
     acc = static_cast<digit_type>(carry);
     carry >>= digit_bits;
   }
-
+
   // phase 3
   for (size_type i = 0; i < ylen - 1; ++i)
   {
@@ -477,6 +511,54 @@
                                       const digit_type* x,
                                       size_type xlen)
 {
+/* word_type acc = 0;
+ word_type carry = 0;
+ word_type acc2;
+
+ for (size_type i = 0; i < xlen; ++i)
+ {
+ // even colum
+ acc += static_cast<word_type>(x[i]) * static_cast<word_type>(x[i]);
+
+ const digit_type* a = x + i;
+ const digit_type* b = x + i;
+
+ acc2 = 0;
+ for (size_type j = 0; j < (i - n&1) >> 1; ++j)
+ {
+ acc2 += static_cast<word_type>(*(--a)) * static_cast<word_type>(*(--b));
+ carry += acc2 >> digit_bits;
+ acc2 = static_cast<digit_type>(acc2);
+ }
+
+ acc += acc2 + acc2;
+
+ *z++ = static_cast<digit_type>(acc);
+ acc = static_cast<digit_type>(carry);
+ carry >>= digit_bits;
+
+ // odd column
+ const digit_type* a = x + i;
+ const digit_type* b = x + i + 1;
+
+ acc2 = 0;
+ for (size_type j = 0; j <= i; ++j)
+ {
+ acc2 += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ carry += acc2 >> digit_bits;
+ acc2 = static_cast<digit_type>(acc2);
+ }
+
+ acc += acc2 + acc2;
+
+ *z++ = static_cast<digit_type>(acc);
+ acc = static_cast<digit_type>(carry);
+ carry >>= digit_bits;
+ }
+
+ *z = static_cast<digit_type>(acc);*/
+
+
   word_type acc = 0; // accumulator for each column
   word_type carry = 0;
 
@@ -520,12 +602,11 @@
 }
 
 template<typename D, typename W, typename S>
-typename basic_primitive_ops<D,W,S>::digit_type
-basic_primitive_ops<D,W,S>::multiply_add_digits(digit_type* z,
- const digit_type* w,
- digit_type x,
- const digit_type* y,
- size_type n)
+D basic_primitive_ops<D,W,S>::multiply_add_digits(digit_type* z,
+ const digit_type* w,
+ digit_type x,
+ const digit_type* y,
+ size_type n)
 {
   word_type carry = 0;
   while (n--)
@@ -543,6 +624,55 @@
 }
 
 
+template<typename D, typename W, typename S>
+inline
+void basic_primitive_ops<D,W,S>::divide_by_two(digit_type* z,
+ const digit_type* x, size_type n)
+{
+ z += n - 1;
+ x += n - 1;
+
+ digit_type carry = 0;
+
+ while (n--)
+ {
+ // get carry for next iteration
+ const digit_type r = *x & 1;
+
+ *z-- = (*x-- >> 1) | (carry << (digit_bits - 1));
+
+ carry = r;
+ }
+}
+
+template<typename D, typename W, typename S>
+D basic_primitive_ops<D,W,S>::divide_by_digit(digit_type* z,
+ const digit_type* x, size_type n,
+ digit_type y)
+{
+ z += n - 1;
+ x += n - 1;
+
+ word_type w = 0;
+
+ while (n--)
+ {
+ w = (w << digit_bits) | static_cast<word_type>(*x--);
+ digit_type tmp;
+ if (w >= y)
+ {
+ tmp = static_cast<digit_type>(w / y);
+ w -= tmp * y;
+ }
+ else
+ tmp = 0;
+ *z-- = tmp;
+ }
+
+ return static_cast<digit_type>(w);
+}
+
+
 
 
 // This exists to ease development of primitive_ops specializations. If a
@@ -558,7 +688,7 @@
 // Here we include primitive_ops specializations that use assembler
 
 #if defined(BOOST_MP_MATH_MP_INT_USE_ASM)
-
+
   #if defined(__GNU__)
     #if defined(__386__)
       #include <boost/mp_math/mp_int/detail/asm/x86/gnu_386_primitive_ops.hpp>

Modified: sandbox/mp_math/boost/mp_math/mp_int/div.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/div.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/div.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -10,61 +10,42 @@
   if (b == 0)
     throw std::domain_error("mp_int::divide_by_digit: division by zero");
 
- if (b == 1 || is_zero())
+ if (b == 1 || !*this)
     return 0;
 
   const bool is_power_of_two = (b & (b-1)) == 0;
- if (is_power_of_two)
- {
- for (int i = 0; i < valid_bits; ++i)
- {
- if (b == digit_type(1) << i)
- {
- const digit_type remainder = digits_[0] & ((digit_type(1) << i) - 1);
- *this >>= i;
- return remainder;
- }
- }
- }
 
- word_type w = 0;
- for (reverse_iterator d = rbegin(); d != rend(); ++d)
+ if (!is_power_of_two)
   {
- w = (w << static_cast<word_type>(valid_bits)) | static_cast<word_type>(*d);
- digit_type tmp;
- if (w >= b)
- {
- tmp = static_cast<digit_type>(w / b);
- w -= tmp * b;
- }
- else
- tmp = 0;
- *d = tmp;
+ const digit_type remainder =
+ ops_type::divide_by_digit(digits(), digits(), size(), b);
+
+ clamp_high_digit();
+
+ if (!*this)
+ set_sign(1);
+
+ return remainder;
   }
 
- clamp();
- if (is_zero())
- set_sign(1);
-
- return static_cast<digit_type>(w);
+ int i = 0;
+ while ((i < valid_bits) && (b != digit_type(1) << i))
+ ++i;
+
+ const digit_type remainder = digits_[0] & ((digit_type(1) << i) - 1);
+ *this >>= i;
+ return remainder;
 }
 
 // *this /= 2
 template<class A, class T>
 void mp_int<A,T>::divide_by_2()
 {
- digit_type carry = 0;
- for (reverse_iterator d = rbegin(); d != rend(); ++d)
- {
- // get the carry for the next iteration
- const digit_type rr = *d & 1;
- // shift the current digit, add in carry and store
- *d = (*d >> 1) | (carry << (valid_bits - 1));
- // forward carry to next iteration
- carry = rr;
- }
- clamp();
- if (is_zero())
+ ops_type::divide_by_two(digits(), digits(), size());
+
+ clamp_high_digit();
+
+ if (!*this)
     set_sign(1);
 }
 
@@ -154,165 +135,15 @@
       carry = rr;
     }
   }
- clamp();
- if (is_zero())
- set_sign(1);
-}
-
-// integer signed division.
-// c*b + d == a [e.g. a/b, c=quotient, d=remainder]
-// HAC pp.598 Algorithm 14.20
-//
-// Note that the description in HAC is horribly incomplete. For example, it
-// doesn't consider the case where digits are removed from 'x' in the inner
-// loop. It also doesn't consider the case that y has fewer than three digits,
-// etc..
-// The overall algorithm is as described as 14.20 from HAC but fixed to treat
-// these cases.
 
-// divide *this by rhs, optionally store remainder
-template<class A, class T>
-void mp_int<A,T>::divide(const mp_int& rhs, mp_int* remainder)
-{
- if (rhs.is_zero())
- throw std::domain_error("mp_int::divide: division by zero");
-
- // if *this < rhs then q=0, r = *this
- if (compare_magnitude(rhs) == -1)
- {
- if (remainder)
- *remainder = *this;
- zero();
- return;
- }
-
- mp_int q;
- q.grow_capacity(size_ + 2);
- q.size_ = size_ + 2;
- std::memset(q.digits_, 0, q.size_ * sizeof(digit_type));
-
- mp_int x(*this);
- mp_int y(rhs);
-
- // fix the sign
- const int neg = (sign() == rhs.sign()) ? 1 : -1;
- x.set_sign(1);
- y.set_sign(1);
-
- // normalize both x and y, ensure that y >= beta/2, [beta == 2**valid_bits]
- size_type norm = y.precision() % valid_bits;
- if (norm < valid_bits-1)
- {
- norm = valid_bits - 1 - norm;
- x <<= norm;
- y <<= norm;
- }
- else
- norm = 0;
-
- // note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4
- const size_type n = x.size_ - 1;
- const size_type t = y.size_ - 1;
-
- // find leading digit of the quotient
- // while (x >= y*beta**(n-t)) do { q[n-t] += 1; x -= y*beta**(n-t) }
- y.shift_digits_left(n - t); // y = y*beta**(n-t)
-
- while (x.compare(y) != -1)
- {
- ++q[n - t];
- x -= y;
- }
-
- // reset y by shifting it back down
- y.shift_digits_right(n - t);
-
- // find the remainder of the digits
- // step 3. for i from n down to (t + 1)
- for (size_type i = n; i >= (t + 1); i--)
- {
- if (i > x.size_)
- continue;
-
- // step 3.1 if xi == yt then set q{i-t-1} to beta-1,
- // otherwise set q{i-t-1} to (xi*beta + x{i-1})/yt
- if (x[i] == y[t])
- q[i - t - 1] = std::numeric_limits<digit_type>::max();
- else
- {
- word_type tmp = static_cast<word_type>(x[i])
- << static_cast<word_type>(valid_bits);
- tmp |= x[i - 1];
- tmp /= y[t];
- q[i - t - 1] = static_cast<digit_type>(tmp);
- }
-
- // now fixup quotient estimation
- // while (q{i-t-1} * (yt * beta + y{t-1})) >
- // xi * beta**2 + xi-1 * beta + xi-2
- //
- // do q{i-t-1} -= 1;
-
- mp_int t1, t2;
- t1.grow_capacity(3);
- t2.grow_capacity(3);
-
- ++q[i - t - 1];
- do
- {
- --q[i - t - 1];
-
- // find left hand
- t1.zero();
- t1[0] = (t == 0) ? 0 : y[t - 1];
- t1[1] = y[t];
- t1.size_ = 2;
- t1.multiply_by_digit(q[i - t - 1]);
-
- // find right hand
- t2[0] = (i < 2) ? 0 : x[i - 2];
- t2[1] = (i == 0) ? 0 : x[i - 1];
- t2[2] = x[i];
- t2.size_ = 3;
- } while (t1.compare_magnitude(t2) == 1);
-
- // step 3.3 x = x - q{i-t-1} * y * beta**{i-t-1}
- t1 = y;
- t1.multiply_by_digit(q[i - t -1]);
- t1.shift_digits_left(i - t - 1);
- x -= t1;
-
- // if x < 0 then { x = x + y*beta**{i-t-1}; q{i-t-1} -= 1; }
- if (x.is_negative())
- {
- t1 = y;
- t1.shift_digits_left(i - t -1);
- x += t1;
-
- --q[i - t - 1] = q[i - t - 1];
- }
- }
-
- // now q is the quotient and x is the remainder [which we have to normalize]
-
- // get sign before writing to *this
- x.set_sign(x.is_zero() ? 1 : sign());
-
- q.clamp();
- swap(q);
- set_sign(neg);
+ clamp();
 
- if (remainder)
- {
- x >>= norm;
- remainder->swap(x);
- }
+ if (!*this)
+ set_sign(1);
 }
 
-/*
 template<class A, class T>
 void divide(const mp_int<A,T>& x, const mp_int<A,T>& y, mp_int<A,T>& q, mp_int<A,T>& r)
 {
- divide(x, y, &q, &r);
+ detail::classic_divide(x, y, q, &r);
 }
-*/

Modified: sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -23,7 +23,7 @@
   if (p <= digit_type(0))
     throw std::domain_error("jacobi: p must be greater than 0");
 
- if (a.is_zero())
+ if (!a)
     return 0;
   
   if (a == digit_type(1))

Modified: sandbox/mp_math/boost/mp_math/mp_int/mod.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/mod.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/mod.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -20,7 +20,8 @@
   digits_[b / valid_bits] &= mask;
   
   clamp();
- if (is_zero())
+
+ if (!*this)
     set_sign(1);
 }
 

Modified: sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -1,4 +1,4 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -20,6 +20,7 @@
 #include <boost/random.hpp>
 #include <boost/type_traits/is_integral.hpp>
 #include <boost/utility/enable_if.hpp>
+#include <boost/mp_math/mp_int/detail/div.hpp>
 #include <boost/mp_math/mp_int/detail/string_conversion_constants.hpp>
 #include <boost/mp_math/mp_int/detail/integral_ops.hpp>
 #include <boost/mp_math/mp_int/detail/meta_math.hpp>
@@ -29,8 +30,6 @@
 namespace boost {
 namespace mp_math {
 
-// digits are stored in least significant order
-
 template<
   class Allocator,
   class Traits
@@ -39,40 +38,60 @@
 :
   Allocator::template rebind<typename Traits::digit_type>::other
 {
- typedef Allocator allocator_type;
- typedef Traits traits_type;
- typedef typename Allocator::size_type size_type;
+private:
+
+ typedef typename Allocator::template
+ rebind<typename Traits::digit_type>::other base_allocator_type;
+
+public:
+
+ typedef Allocator allocator_type;
+ typedef Traits traits_type;
+ typedef typename base_allocator_type::size_type size_type;
 
   mp_int();
 
+ explicit mp_int(const allocator_type& a);
+
   template<typename IntegralT>
- mp_int(IntegralT, typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
+ mp_int(IntegralT,
+ const allocator_type& a = allocator_type(),
+ typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
 
   template<typename charT>
- mp_int(const charT*);
+ mp_int(const charT*, const allocator_type& a = allocator_type());
 
   template<typename charT>
- mp_int(const charT*, std::ios_base::fmtflags);
+ mp_int(const charT*,
+ std::ios_base::fmtflags,
+ const allocator_type& a = allocator_type());
 
   template<typename charT, class traits, class Alloc>
- mp_int(const std::basic_string<charT,traits,Alloc>&);
-
+ mp_int(const std::basic_string<charT,traits,Alloc>&,
+ const allocator_type& a = allocator_type());
+
   template<typename charT, class traits, class Alloc>
- mp_int(const std::basic_string<charT,traits,Alloc>&, std::ios_base::fmtflags);
-
+ mp_int(const std::basic_string<charT,traits,Alloc>&,
+ std::ios_base::fmtflags,
+ const allocator_type& a = allocator_type());
+
   template<typename RandomAccessIterator>
- mp_int(RandomAccessIterator first, RandomAccessIterator last);
-
+ mp_int(RandomAccessIterator first,
+ RandomAccessIterator last,
+ const allocator_type& a = allocator_type());
+
   template<typename RandomAccessIterator>
- mp_int(RandomAccessIterator first, RandomAccessIterator last,
- std::ios_base::fmtflags f);
+ mp_int(RandomAccessIterator first,
+ RandomAccessIterator last,
+ std::ios_base::fmtflags f,
+ const allocator_type& a = allocator_type());
 
   mp_int(const mp_int& copy);
 
   #ifdef BOOST_HAS_RVALUE_REFS
   mp_int(mp_int&& copy);
   #endif
-
+
   ~mp_int();
 
   mp_int& operator = (const mp_int& rhs);
@@ -80,7 +99,7 @@
   #ifdef BOOST_HAS_RVALUE_REFS
   mp_int& operator = (mp_int&& rhs);
   #endif
-
+
   template<typename IntegralT>
   mp_int& operator = (IntegralT rhs);
 
@@ -95,8 +114,8 @@
 
   template<typename charT, class traits, class Alloc>
   void assign(const std::basic_string<charT,traits,Alloc>&,
- std::ios_base::fmtflags);
-
+ std::ios_base::fmtflags);
+
   template<typename RandomAccessIterator>
   void assign(RandomAccessIterator first, RandomAccessIterator last,
               std::ios_base::fmtflags);
@@ -169,7 +188,7 @@
 
   operator unspecified_bool_type() const
   {
- return is_zero() ? 0 : &mp_int::size_;
+ return !(size_ == 1 && digits_[0] == 0) ? &mp_int::size_ : 0;
   }
 
   bool is_even() const { return (digits_[0] & digit_type(1)) == 0; }
@@ -224,13 +243,14 @@
 
   digit_type& operator[](size_type i) { return digits_[i]; }
   const digit_type& operator[](size_type i) const { return digits_[i]; }
-
+
   digit_type& at(size_type i)
   {
     if (i >= size_)
       throw std::out_of_range("mp_int::at: array subscript out of range");
     return digits_[i];
   }
+
   const digit_type& at(size_type i) const
   {
     if (i >= size_)
@@ -247,7 +267,7 @@
   void print(bool all=false) const;
   bool test_invariants() const;
 
- bool is_uninitialized() const { return size_ == 0U; }
+ bool is_uninitialized() const { return !size_; }
 
   size_type size() const { return size_; }
   size_type capacity() const
@@ -281,6 +301,7 @@
 
   void grow_capacity(size_type n);
   void clamp();
+ void clamp_high_digit();
 
   int compare_magnitude(const mp_int& rhs) const;
   int compare_to_digit(digit_type) const;
@@ -289,7 +310,6 @@
   void add_magnitude(const mp_int& rhs);
   void sub_smaller_magnitude(const mp_int& rhs);
 
- bool is_zero() const;
   bool is_power_of_two() const;
   void add_digit(digit_type);
   void sub_digit(digit_type);
@@ -312,7 +332,6 @@
   void comba_sqr();
 
   digit_type divide_by_digit(digit_type); // returns remainder
- void divide(const mp_int& divisor, mp_int* remainder);
   void divide_by_2();
   digit_type divide_by_3();
   void modulo_2_to_the_power_of(size_type);
@@ -326,13 +345,22 @@
   {
     digits_[0] |= digit_type(1);
   }
-
+
   void set_bit(size_type bit)
   {
- digits_[bit / valid_bits] |=
- digit_type(1) << digit_type(bit % valid_bits);
+ digits_[bit / valid_bits] |= digit_type(1) << (bit % valid_bits);
   }
 
+ void clear_bit(size_type bit)
+ {
+ digits_[bit / valid_bits] &= ~(digit_type(1) << (bit % valid_bits));
+ }
+
+ void set_bits(size_type beg, size_type end);
+ void clear_bits(size_type beg, size_type end);
+
+ void truncate(size_type prec);
+
   template<class A, class T>
   friend bool operator == (const mp_int<A,T>&, const mp_int<A,T>&);
 
@@ -343,7 +371,7 @@
   void from_string(Iter first, Iter last, unsigned radix);
 
 private:
-
+
   digit_type* digits_;
   size_type size_, capacity_;
 };
@@ -364,7 +392,7 @@
       cout << ",";
   }
   cout << "}";
-
+
   if (all)
   {
     cout << capacity() - size_ << "{";
@@ -388,7 +416,7 @@
       return false;
     if (digits_[size_-1] == 0U)
       return false;
- if (is_zero() && sign() != 1)
+ if (!*this && sign() != 1)
       return false;
   }
   return true;
@@ -417,7 +445,8 @@
 {
   if (this != &rhs)
   {
- this->deallocate(digits_, capacity());
+ if (digits_)
+ this->deallocate(digits_, capacity());
     digits_ = 0;
     size_ = 0;
     capacity_ = 0;
@@ -592,15 +621,16 @@
 template<class A, class T>
 void mp_int<A,T>::clamp()
 {
- // decrease size_ while the most significant digit is zero.
   while (size_ > 1 && digits_[size_-1] == 0)
     --size_;
 }
 
+// For when we know that only one leading zero digit may exist.
 template<class A, class T>
-inline bool mp_int<A,T>::is_zero() const
+inline void mp_int<A,T>::clamp_high_digit()
 {
- return size_ == 1 && digits_[0] == 0;
+ if (size_ > 1 && digits_[size_-1] == 0)
+ --size_;
 }
 
 // disregards the sign of the numbers
@@ -613,7 +643,7 @@
   // compare based on # of non-zero digits
   if (size_ > rhs.size_)
     return 1;
-
+
   if (size_ < rhs.size_)
     return -1;
 
@@ -660,7 +690,7 @@
     else
       return 1;
   }
-
+
   if (is_negative())
     // if negative compare opposite direction
     return rhs.compare_magnitude(*this);
@@ -705,7 +735,7 @@
 
   // zero the top digits
   std::memset(digits_ + size_ - b, 0, b * sizeof(digit_type));
-
+
   // remove excess digits
   size_ -= b;
 }
@@ -716,7 +746,7 @@
 {
   // get number of digits and add that
   size_type r = (size_ - 1) * valid_bits;
-
+
   // take the last digit and count the bits in it
   digit_type q = digits_[size_ - 1];
   while (q > 0U)
@@ -736,7 +766,7 @@
     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
   };
 
- if (is_zero())
+ if (!*this)
     return 0;
 
   // scan lower digits until non-zero
@@ -767,6 +797,67 @@
   return detail::integral_ops<IntegralT>::convert(*this);
 }
 
+template<class A, class T>
+void mp_int<A,T>::set_bits(size_type beg, size_type end)
+{
+ const size_type beg_index = beg / digit_bits;
+ const size_type end_index = end / digit_bits;
+ const size_type first_bits = beg % digit_bits;
+ const size_type last_bits = end % digit_bits;
+
+ static const digit_type z = ~digit_type(0);
+
+ digit_type mask = z << first_bits;
+ if (beg_index == end_index && last_bits)
+ mask &= z >> (digit_bits - last_bits);
+
+ digits_[beg_index] |= mask;
+
+ for (size_type i = beg_index + ((beg % digit_bits) ? 1 : 0); i < end_index; ++i)
+ digits_[i] = digit_max;
+
+ if (beg_index != end_index && last_bits)
+ digits_[end_index] |= z >> (digit_bits - last_bits);
+}
+
+template<class A, class T>
+void mp_int<A,T>::clear_bits(size_type beg, size_type end)
+{
+ const size_type beg_index = beg / digit_bits;
+ const size_type end_index = end / digit_bits;
+ const size_type first_bits = beg % digit_bits;
+ const size_type last_bits = end % digit_bits;
+
+ static const digit_type z = ~digit_type(0);
+
+ digit_type mask;
+ if (first_bits)
+ mask = z >> (digit_bits - first_bits);
+ else
+ mask = 0;
+
+ if (beg_index == end_index)
+ mask |= z << last_bits;
+
+ digits_[beg_index] &= mask;
+
+ if (beg_index != end_index)
+ {
+ std::memset(digits_ + beg_index + 1, 0,
+ sizeof(digit_type) * (end_index - beg_index - 1));
+
+ digits_[end_index] &= z << last_bits;
+ }
+}
+
+template<class A, class T>
+void mp_int<A,T>::truncate(size_type prec)
+{
+ set_size((prec + digit_bits - 1)/digit_bits);
+ const size_type last_bits = prec % digit_bits;
+ digits_[size()] &= ~digit_type(0) << (digit_bits - last_bits);
+}
+
 
 template<class A, class T>
 inline void swap(mp_int<A,T>& lhs, mp_int<A,T>& rhs)

Modified: sandbox/mp_math/boost/mp_math/mp_int/mul.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/mul.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/mul.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -18,7 +18,8 @@
   // make sure we can hold the result
   grow_capacity(size_ + 1);
   
- const digit_type carry = ops_type::multiply_by_digit(digits_, digits_, size_, x);
+ const digit_type carry =
+ ops_type::multiply_by_digit(digits(), digits(), size(), x);
 
   if (carry)
     push(carry);
@@ -30,27 +31,11 @@
 {
   grow_capacity(size_ + 1);
 
- digit_type carry = 0;
- for (iterator d = begin(); d != end(); ++d)
- {
- // get what will be the *next* carry bit from the
- // MSB of the current digit
- const digit_type rr = *d >> (static_cast<digit_type>(valid_bits - 1));
-
- // now shift up this digit, add in the carry [from the previous]
- *d = (*d << digit_type(1)) | carry;
-
- // copy the carry that would be from the source
- // digit into the next iteration
- carry = rr;
- }
+ const digit_type carry =
+ ops_type::multiply_by_two(digits(), digits(), size());
 
- // new leading digit?
   if (carry)
- {
- // add a MSB which is always 1 at this point
- push(1);
- }
+ push(carry);
 }
 
 
@@ -310,8 +295,10 @@
   }
 
   tmp.clamp();
- if (tmp.is_zero())
+
+ if (!tmp)
     tmp.set_sign(1);
+
   swap(tmp);
 }
 
@@ -350,8 +337,10 @@
   }
 
   tmp.clamp();
- if (tmp.is_zero())
+
+ if (!tmp)
     tmp.set_sign(1);
+
   swap(tmp);
 }
 

Modified: sandbox/mp_math/boost/mp_math/mp_int/operators.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/operators.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/operators.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -283,7 +283,7 @@
     }
     
     if (carry)
- digits_[size_++] = carry;
+ push(carry);
   }
 
   clamp();
@@ -301,7 +301,7 @@
 template<class A, class T>
 inline mp_int<A,T>& mp_int<A,T>::operator - ()
 {
- if (!is_zero())
+ if (*this)
     set_sign(sign() == 1 ? -1 : 1);
   return *this;
 }
@@ -341,7 +341,8 @@
     size_ = x->size_;
 
     clamp();
- if (is_zero())
+
+ if (!*this)
       set_sign(1);
   }
   return *this;
@@ -378,7 +379,8 @@
     size_ = x->size_;
     
     clamp();
- if (is_zero())
+
+ if (!*this)
       set_sign(1);
   }
   return *this;
@@ -420,18 +422,19 @@
 
     tmp.size_ = size_ + rhs.size_;
     tmp.clamp();
- swap(tmp);
+ *this = tmp;
   }
 
- set_sign(is_zero() ? 1 : neg);
+ set_sign(!*this ? 1 : neg);
 
   return *this;
 }
 
 template<class A, class T>
-inline mp_int<A,T>& mp_int<A,T>::operator /= (const mp_int<A,T>& rhs)
+mp_int<A,T>& mp_int<A,T>::operator /= (const mp_int<A,T>& rhs)
 {
- divide(rhs, 0);
+ const mp_int<A,T> tmp(*this);
+ detail::classic_divide(tmp, rhs, *this);
   return *this;
 }
 
@@ -439,9 +442,8 @@
 template<class A, class T>
 mp_int<A,T>& mp_int<A,T>::operator %= (const mp_int<A,T>& rhs)
 {
- mp_int<A,T> remainder;
- divide(rhs, &remainder);
- swap(remainder);
+ mp_int<A,T> quotient;
+ detail::classic_divide(*this, rhs, quotient, this);
   return *this;
 }
 

Modified: sandbox/mp_math/boost/mp_math/mp_int/root.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/root.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/root.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -1,4 +1,4 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -20,7 +20,7 @@
 
   mp_int<A,T> t1;
 
- if (x.is_zero())
+ if (!x)
   {
     t1.zero();
     return t1;
@@ -49,35 +49,39 @@
 }
 
 
-// find the n'th root of an integer
-//
-// Result found such that (c)**b <= a and (c+1)**b > a
-//
-// This algorithm uses Newton's approximation
-// x[i+1] = x[i] - f(x[i])/f'(x[i])
-// which will find the root in log(N) time where
-// each step involves a fair bit. This is not meant to
-// find huge roots [square and cube, etc].
+// Uses Newton-Raphson approximation.
 template<class A, class T>
 mp_int<A,T> nth_root(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n)
 {
   if ((n & 1) == 0 && x.is_negative())
     throw std::domain_error("nth_root: argument must be positive if n is even");
 
+ if (n == 0U)
+ throw std::domain_error("nth_root: n must not be zero");
+ else if (n == 1U)
+ return x;
+
   // if x is negative fudge the sign but keep track
   const int neg = x.sign();
   const_cast<mp_int<A,T>*>(&x)->set_sign(1);
 
   mp_int<A,T> t1, t2, t3;
-
- t2 = typename mp_int<A,T>::digit_type(2);
+
+ typedef typename mp_int<A,T>::size_type size_type;
+
+ // initial approximation
+ const size_type result_precision = (x.precision() - 1) / n + 1;
+ t2.grow_capacity(1);
+ t2.set_size(1);
+ t2[0] = 0;
+ t2.set_bits(0, result_precision + 1);
 
   do
   {
     t1 = t2;
 
     // t2 = t1 - ((t1**n - x) / (n * t1**(n-1)))
-
+
     // t3 = t1**(n-1)
     t3 = pow(t1, n-1);
 
@@ -97,7 +101,7 @@
 
     t2 = t1 - t3;
   } while (t1 != t2);
-
+
   // result can be off by a few so check
   for (;;)
   {
@@ -132,15 +136,26 @@
   const_cast<mp_int<A,T>*>(&x)->set_sign(1);
 
   mp_int<A,T> t1, t2, t3;
-
- t2 = typename mp_int<A,T>::digit_type(2);
+
+ typedef typename mp_int<A,T>::size_type size_type;
+
+ static const size_type digit_bits = mp_int<A,T>::digit_bits;
+
+ const size_type result_precision = (x.precision() - 1)
+ / n.template to_integral<size_type>() + 1;
+
+ t2.grow_capacity((result_precision + digit_bits - 1) / digit_bits);
+ t2.set_size ((result_precision + digit_bits - 1) / digit_bits);
+
+ t2[t2.size()-1] = 0;
+ t2.set_bits(0, result_precision + 1);
 
   do
   {
     t1 = t2;
 
     // t2 = t1 - ((t1**n - x) / (n * t1**(n-1)))
-
+
     // t3 = t1**(n-1)
     t3 = pow(t1, n-1);
 
@@ -160,7 +175,7 @@
 
     t2 = t1 - t3;
   } while (t1 != t2);
-
+
   // result can be off by a few so check
   for (;;)
   {

Modified: sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -174,15 +174,35 @@
 template<class A, class T>
 void mp_int<A,T>::comba_sqr()
 {
- mp_int tmp;
- tmp.grow_capacity(size_ + size_);
+ if (size() < 16U)
+ {
+ grow_capacity(size() + size());
+
+ digit_type Z[32];
+
+ ops_type::comba_sqr(Z, digits(), size());
+
+ std::memcpy(digits(), Z, (size() + size()) * sizeof(digit_type));
+
+ set_size(size() + size());
+
+ if (!digits()[size()-1])
+ pop();
+ }
+ else
+ {
+ mp_int tmp;
+ tmp.grow_capacity(size() + size());
+
+ ops_type::comba_sqr(tmp.digits(), digits(), size());
+
+ tmp.set_size(size() + size());
 
- ops_type::comba_sqr(tmp.digits(), digits(), size_);
+ if (!tmp[tmp.size()-1])
+ tmp.pop();
 
- tmp.size_ = size_ + size_;
-
- tmp.clamp();
- swap(tmp);
+ *this = tmp;
+ }
 }
 
 // computes *this = *this * *this

Modified: sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp (original)
+++ sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -64,17 +64,18 @@
       
       if (offset >= valid_bits)
       {
- digits_[size_++] = result;
+ push(result);
         offset -= valid_bits;
         result = static_cast<digit_type>(x >> (sc.radix_storage_bits - offset));
       }
     }
     
- if (result || !size_)
- digits_[size_++] = result;
+ if (result || is_uninitialized())
+ push(result);
     
     clamp();
- if (is_zero())
+
+ if (!*this)
       set_sign(1);
   }
   else // radix can only be 10 at this point
@@ -112,16 +113,16 @@
         carry += ops_type::add_single_digit(digits_, digits_, size_, result);
         
         if (carry)
- digits_[size_++] = carry;
+ push(carry);
       }
       else
- digits_[size_++] = result;
+ push(result);
     }
 
     // one last round for the remaining decimal digits
     if (first != last)
     {
- word_type radix_power = 1U;
+ digit_type radix_power = 1U;
       digit_type result = 0U;
       
       while (first != last)
@@ -141,10 +142,10 @@
         carry += ops_type::add_single_digit(digits_, digits_, size_, result);
 
         if (carry)
- digits_[size_++] = carry;
+ push(carry);
       }
       else
- digits_[size_++] = result;
+ push(result);
     }
   }
 }
@@ -174,7 +175,7 @@
 
   StringT s;
 
- if (!size_)
+ if (is_uninitialized())
     return s;
 
   digit_type radix;
@@ -212,7 +213,7 @@
 
   const int prefix_offset = p - prefix;
 
- if (is_zero())
+ if (!*this)
   {
     s.reserve(prefix_offset + 1);
     for (int i = 0; i < prefix_offset; ++i)
@@ -258,7 +259,7 @@
                           ? uppercase_tab
                           : lowercase_tab;
     
- const digit_type mask = (1 << sc.radix_storage_bits) - 1;
+ const digit_type mask = (digit_type(1) << sc.radix_storage_bits) - 1;
 
     int offset = total_bits % valid_bits;
     if (!offset)
@@ -288,14 +289,18 @@
     
     mp_int tmp = abs(*this);
     
- while (!tmp.is_zero())
+ while (tmp)
     {
- digit_type remainder = tmp.divide_by_digit(sc.max_power_value);
-
+ digit_type remainder = ops_type::divide_by_digit(tmp.digits(),
+ tmp.digits(),
+ tmp.size(),
+ sc.max_power_value);
+ tmp.clamp_high_digit();
+
       for (digit_type i = 0; i < m; ++i)
       {
- if (remainder || !tmp.is_zero())
- *c++ = '0' + remainder % 10U;
+ if (remainder || tmp)
+ *c++ = static_cast<char_type>('0' + remainder % 10U);
         remainder /= 10U;
       }
     }

Added: sandbox/mp_math/libs/mp_math/test/bitmanipulation.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/bitmanipulation.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -0,0 +1,78 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits1, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0xff00000000ff");
+ x.set_bits(8, 40);
+ BOOST_CHECK_EQUAL(x, "0xffffffffffff");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits2, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x8000");
+ x.set_bits(2, 7);
+ BOOST_CHECK_EQUAL(x, "0x807c");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits3, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x80000000000000");
+ x.set_bits(12, 13);
+ BOOST_CHECK_EQUAL(x, "0x80000000001000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits4, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x8000000000000000");
+ x.set_bits(0, 18);
+ BOOST_CHECK_EQUAL(x, "0x800000000003FFFF");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits5, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x80000000");
+ x.set_bits(8, 16);
+ BOOST_CHECK_EQUAL(x, "0x8000FF00");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits1, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0xffffffffffff");
+ x.clear_bits(8, 40);
+ BOOST_CHECK_EQUAL(x, "0xff00000000ff");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits2, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x807c");
+ x.clear_bits(2, 7);
+ BOOST_CHECK_EQUAL(x, "0x8000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits3, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x80000000001000");
+ x.clear_bits(12, 13);
+ BOOST_CHECK_EQUAL(x, "0x80000000000000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits4, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x800000000003FFFF");
+ x.clear_bits(0, 18);
+ BOOST_CHECK_EQUAL(x, "0x8000000000000000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits5, mp_int_type, mp_int_types)
+{
+ mp_int_type x("0x8000FF00");
+ x.clear_bits(8, 16);
+ BOOST_CHECK_EQUAL(x, "0x80000000");
+}
+

Modified: sandbox/mp_math/libs/mp_math/test/cmp.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/cmp.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/cmp.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -130,6 +130,12 @@
   BOOST_CHECK_LE(x, 32102);
 }
 
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_le_integral_type3, mp_int_type, mp_int_types)
+{
+ const mp_int_type x("0x100000000");
+ BOOST_CHECK_LE(1, x);
+}
+
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_le_unsigned_integral_type, mp_int_type, mp_int_types)
 {

Modified: sandbox/mp_math/libs/mp_math/test/ctors.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/ctors.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/ctors.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -37,7 +37,7 @@
 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_decimal_string4, mp_int_type, mp_int_types)
 {
   const mp_int_type y("0");
- BOOST_CHECK_EQUAL(y.is_zero(), true);
+ BOOST_CHECK_EQUAL(!y, true);
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_positive_decimal_string1, mp_int_type, mp_int_types)
@@ -67,7 +67,7 @@
 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_octal_string2, mp_int_type, mp_int_types)
 {
   const mp_int_type y("000000000000000000000000000000000");
- BOOST_CHECK_EQUAL(y.is_zero(), true);
+ BOOST_CHECK_EQUAL(!y, true);
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_octal_string3, mp_int_type, mp_int_types)

Modified: sandbox/mp_math/libs/mp_math/test/div.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/div.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/div.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -30,6 +30,22 @@
   BOOST_CHECK_EQUAL(z, "2137");
 }
 
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide4, mp_int_type, mp_int_types)
+{
+ const mp_int_type x("0x89ab89745cc653de58eecc8f8a874120065ea545f6f5f");
+ const mp_int_type y("0x1889ba8a789456adfc8005b1");
+ const mp_int_type z = x / y;
+ BOOST_CHECK_EQUAL(z, "0x59c48aa7a1446110b31f70");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide5, mp_int_type, mp_int_types)
+{
+ const mp_int_type x("0x1889ba8a789456adfc8005b1");
+ const mp_int_type y("0x1889ba8a789456adfc8005b2");
+ const mp_int_type z = x / y;
+ BOOST_CHECK_EQUAL(z, "0");
+}
+
 BOOST_AUTO_TEST_CASE_TEMPLATE(divide_by_2, mp_int_type, mp_int_types)
 {
   mp_int_type x("263825472");

Modified: sandbox/mp_math/libs/mp_math/test/integral_ops.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/integral_ops.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/integral_ops.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -9,7 +9,7 @@
 BOOST_AUTO_TEST_CASE_TEMPLATE(construct_from_zero, mp_int_type, mp_int_types)
 {
   const mp_int_type x(0);
- BOOST_CHECK_EQUAL(x.is_zero(), true);
+ BOOST_CHECK_EQUAL(!x, true);
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(equal_signed_char_min, mp_int_type, mp_int_types)
@@ -190,6 +190,21 @@
   BOOST_CHECK_EQUAL(z, "0");
 }
 
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide_by_unsigned_char1, mp_int_type, mp_int_types)
+{
+ const unsigned char y = 16;
+ const mp_int_type x("10000001");
+ const mp_int_type z = x / y;
+ BOOST_CHECK_EQUAL(z, "625000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide_by_unsigned_char2, mp_int_type, mp_int_types)
+{
+ const unsigned char y = 128;
+ const mp_int_type x("14222200");
+ const mp_int_type z = x / y;
+ BOOST_CHECK_EQUAL(z, "111110");
+}
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(divide_by_signed_integral1, mp_int_type, mp_int_types)
 {

Modified: sandbox/mp_math/libs/mp_math/test/jamfile.v2
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/jamfile.v2 (original)
+++ sandbox/mp_math/libs/mp_math/test/jamfile.v2 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -1,4 +1,4 @@
-# Copyright Kevin Sopp 2008.
+# Copyright Kevin Sopp 2008 - 2009.
 # Distributed under the Boost Software License, Version 1.0.
 # (See accompanying file LICENSE_1_0.txt or copy at
 # http://www.boost.org/LICENSE_1_0.txt)
@@ -7,18 +7,19 @@
 : $(BOOST_ROOT)/libs/test/build//boost_unit_test_framework/<link>shared ;
 
 alias boost_serialization
-: $(BOOST_ROOT)/libs/serialization/build//boost_serialization/<link>shared ;
+: $(BOOST_ROOT)/libs/serialization/build//boost_serialization/<link>shared ;
 
 project
- : requirements
- <include>../../..
- <link>static
- <define>BOOST_TEST_DYN_LINK
- <define>BOOST_TEST_MAIN
- #<define>BOOST_MP_MATH_MP_INT_USE_ASM
- ;
+ : requirements
+ <include>../../..
+ <link>static
+ <define>BOOST_TEST_DYN_LINK
+ <define>BOOST_TEST_MAIN
+ <define>BOOST_MP_MATH_MP_INT_USE_ASM
+ ;
 
 unit-test add : add.cpp boost_test ;
+unit-test bitmanipulation : bitmanipulation.cpp boost_test ;
 unit-test bitwise_ops : bitwise_ops.cpp boost_test ;
 unit-test bool_conversion : bool_conversion.cpp boost_test ;
 unit-test cmp : cmp.cpp boost_test ;

Modified: sandbox/mp_math/libs/mp_math/test/root.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/root.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/root.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -27,3 +27,17 @@
   BOOST_CHECK_EQUAL(y, "441");
 }
 
+BOOST_AUTO_TEST_CASE_TEMPLATE(nth_root2, mp_int_type, mp_int_types)
+{
+ const mp_int_type x(
+ "0x2b93d251afa09c5481f4522279f7c19ca08124199621dfd18342a16c7303b31ccea8176b"
+ "d4a7a9bf991e30d8bde1e08356a728b9f5729c35d29884050101341228c5df3f98354d42b7"
+ "a0d7fdfbe8d5270b09ee89ba1eeab61be67eb4471d92fdffa88d1ca494ed3eec58a34ff958"
+ "b518a588584a2505c9c2b19ce1eb21cba36c7a5297cb6e532884e89451f4406b993582f3cd"
+ "b75cab98f8c4c6f3837977db2a594dfa16943062187ca95babc9da78bdd73ca7233eefc047"
+ "8d882e0d4f09a5083a31b801964343d47b6ce9e937df8c44a9a02bac5101da1823373e663c"
+ "1329ece1eb89fc178355660fe1c92c7d8ff11524702fad6e2255447946442356b00810101");
+ const mp_int_type y = nth_root(x, mp_int_type("257"));
+ BOOST_CHECK_EQUAL(y, "257");
+}
+

Modified: sandbox/mp_math/libs/mp_math/test/shift.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/shift.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/shift.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -40,3 +40,10 @@
   x >>= 17;
   BOOST_CHECK_EQUAL(x, "0");
 }
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(right_shift3, mp_int_type, mp_int_types)
+{
+ mp_int_type x("14222200");
+ x >>= 8;
+ BOOST_CHECK_EQUAL(x, "55555");
+}

Modified: sandbox/mp_math/libs/mp_math/test/string_ops.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/string_ops.cpp (original)
+++ sandbox/mp_math/libs/mp_math/test/string_ops.cpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -119,7 +119,7 @@
 {
   mp_int_type x;
   x = "0";
- BOOST_CHECK_EQUAL(x.is_zero(), true);
+ BOOST_CHECK_EQUAL(!x, true);
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(op_assign5, mp_int_type, mp_int_types)

Modified: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp (original)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -84,7 +84,7 @@
     explicit square_op(base& ba) : b(ba) {}
     void operator()(unsigned int i) const
     {
- mpz_pow_ui(b.dst[i].get_mpz_t(), b.src1[i].get_mpz_t(), 2);
+ b.dst[i] = b.src1[i] * b.src1[i];
     }
   };
 

Modified: sandbox/mp_math/project-root.jam
==============================================================================
--- sandbox/mp_math/project-root.jam (original)
+++ sandbox/mp_math/project-root.jam 2009-01-10 19:30:26 EST (Sat, 10 Jan 2009)
@@ -10,13 +10,11 @@
 ## IMPORTANT NOTE: This file MUST NOT be copied over a boost installation
 ##
 
-path-constant top : . ;
 
 import modules ;
 import path ;
 
 local boost-root = [ modules.peek : BOOST_ROOT ] ;
-local math-header-include = $(top)/../.. ;
 
 if ! $(boost-root)
 {


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