Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r77260 - in sandbox/big_number: boost/multiprecision libs/multiprecision/test
From: john_at_[hidden]
Date: 2012-03-08 05:34:38


Author: johnmaddock
Date: 2012-03-08 05:34:37 EST (Thu, 08 Mar 2012)
New Revision: 77260
URL: http://svn.boost.org/trac/boost/changeset/77260

Log:
Add support for fixed precision and unsigned cpp_int's.
Text files modified:
   sandbox/big_number/boost/multiprecision/cpp_int.hpp | 1074 ++++++++++++++++++++++++++++-----------
   sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp | 2
   sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp | 144 ++--
   sandbox/big_number/libs/multiprecision/test/test_numeric_limits.cpp | 13
   4 files changed, 846 insertions(+), 387 deletions(-)

Modified: sandbox/big_number/boost/multiprecision/cpp_int.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/cpp_int.hpp (original)
+++ sandbox/big_number/boost/multiprecision/cpp_int.hpp 2012-03-08 05:34:37 EST (Thu, 08 Mar 2012)
@@ -19,8 +19,11 @@
 namespace boost{
 namespace multiprecision{
 
-template <unsigned InternalLimbs = 0, class Allocator = std::allocator<limb_type> >
-struct cpp_int_backend : private Allocator::template rebind<limb_type>::other
+template <unsigned MinBits = 0, bool Signed = true, class Allocator = std::allocator<limb_type> >
+struct cpp_int_backend;
+
+template <unsigned MinBits = 0, bool Signed = true, class Allocator = std::allocator<limb_type> >
+struct cpp_int_base : private Allocator::template rebind<limb_type>::other
 {
    typedef typename Allocator::template rebind<limb_type>::other allocator_type;
    typedef typename allocator_type::pointer limb_pointer;
@@ -34,17 +37,18 @@
    };
 
 public:
- typedef mpl::list<signed_limb_type, signed_double_limb_type> signed_types;
- typedef mpl::list<limb_type, double_limb_type> unsigned_types;
- typedef mpl::list<long double> float_types;
-
    BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
    BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
    BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
- BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = InternalLimbs ? InternalLimbs : sizeof(limb_data) / sizeof(limb_type));
+ BOOST_STATIC_CONSTANT(unsigned, internal_limb_count =
+ MinBits
+ ? MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0)
+ : sizeof(limb_data) / sizeof(limb_type));
+ BOOST_STATIC_CONSTANT(bool, variable = true);
 
-private:
+ BOOST_STATIC_ASSERT_MESSAGE(Signed, "There is curently no support for unsigned arbitrary precision integers.");
 
+private:
    union data_type
    {
       limb_data ld;
@@ -56,7 +60,6 @@
    bool m_sign, m_internal;
 
 public:
-
    //
    // Helper functions for getting at our internal data, and manipulating storage:
    //
@@ -98,19 +101,24 @@
          m_limbs = new_size;
       }
    }
+ void normalize()
+ {
+ limb_pointer p = limbs();
+ while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
+ }
 
- cpp_int_backend() : m_limbs(1), m_sign(false), m_internal(true)
+ cpp_int_base() : m_limbs(1), m_sign(false), m_internal(true)
    {
       *limbs() = 0;
    }
- cpp_int_backend(const cpp_int_backend& o) : m_limbs(0), m_internal(true)
+ cpp_int_base(const cpp_int_base& o) : m_limbs(0), m_internal(true)
    {
       resize(o.size());
       std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
       m_sign = o.m_sign;
    }
 #ifndef BOOST_NO_RVALUE_REFERENCES
- cpp_int_backend(cpp_int_backend&& o) : m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal)
+ cpp_int_base(cpp_int_base&& o) : m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal)
    {
       if(m_internal)
       {
@@ -124,12 +132,12 @@
       }
    }
 #endif
- ~cpp_int_backend()
+ ~cpp_int_base()
    {
       if(!m_internal)
          allocator().deallocate(limbs(), capacity());
    }
- cpp_int_backend& operator = (const cpp_int_backend& o)
+ void assign(const cpp_int_base& o)
    {
       if(this != &o)
       {
@@ -138,20 +146,242 @@
          std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
          m_sign = o.m_sign;
       }
+ }
+ void negate()
+ {
+ m_sign = !m_sign;
+ // Check for zero value:
+ if(m_sign && (m_limbs == 1))
+ {
+ if(limbs()[0] == 0)
+ m_sign = false;
+ }
+ }
+ bool isneg()const
+ {
+ return m_sign;
+ }
+ void do_swap(cpp_int_base& o)
+ {
+ std::swap(m_data, o.m_data);
+ std::swap(m_sign, o.m_sign);
+ std::swap(m_internal, o.m_internal);
+ std::swap(m_limbs, o.m_limbs);
+ }
+};
+
+template <unsigned MinBits>
+struct cpp_int_base<MinBits, true, void>
+{
+ typedef limb_type* limb_pointer;
+ typedef const limb_type* const_limb_pointer;
+
+public:
+ BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
+ BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
+ BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
+ BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0));
+ BOOST_STATIC_CONSTANT(bool, variable = false);
+ BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
+
+private:
+ limb_type m_data[internal_limb_count];
+ boost::uint16_t m_limbs;
+ bool m_sign;
+
+public:
+ //
+ // Helper functions for getting at our internal data, and manipulating storage:
+ //
+ unsigned size()const { return m_limbs; }
+ limb_pointer limbs() { return m_data; }
+ const_limb_pointer limbs()const { return m_data; }
+ bool sign()const { return m_sign; }
+ void sign(bool b)
+ {
+ m_sign = b;
+ // Check for zero value:
+ if(m_sign && (m_limbs == 1))
+ {
+ if(limbs()[0] == 0)
+ m_sign = false;
+ }
+ }
+ void resize(unsigned new_size)
+ {
+ m_limbs = (std::min)(new_size, internal_limb_count);
+ }
+ void normalize()
+ {
+ limb_pointer p = limbs();
+ while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
+ }
+
+ cpp_int_base() : m_limbs(1), m_sign(false)
+ {
+ *limbs() = 0;
+ }
+ cpp_int_base(const cpp_int_base& o) : m_limbs(0)
+ {
+ resize(o.size());
+ std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
+ m_sign = o.m_sign;
+ }
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ cpp_int_base(cpp_int_base&& o) : m_limbs(o.m_limbs), m_sign(o.m_sign)
+ {
+ std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
+ }
+#endif
+ ~cpp_int_base() {}
+ void assign(const cpp_int_base& o)
+ {
+ if(this != &o)
+ {
+ resize(o.size());
+ std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
+ m_sign = o.m_sign;
+ }
+ }
+ void negate()
+ {
+ m_sign = !m_sign;
+ // Check for zero value:
+ if(m_sign && (m_limbs == 1))
+ {
+ if(limbs()[0] == 0)
+ m_sign = false;
+ }
+ }
+ bool isneg()const
+ {
+ return m_sign;
+ }
+ void do_swap(cpp_int_base& o)
+ {
+ for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
+ std::swap(m_data[i], o.m_data[i]);
+ std::swap(m_sign, o.m_sign);
+ std::swap(m_limbs, o.m_limbs);
+ }
+};
+
+template <unsigned MinBits>
+struct cpp_int_base<MinBits, false, void>
+{
+ typedef limb_type* limb_pointer;
+ typedef const limb_type* const_limb_pointer;
+
+public:
+ BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
+ BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
+ BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
+ BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0));
+ BOOST_STATIC_CONSTANT(bool, variable = false);
+ BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs");
+
+private:
+ limb_type m_data[internal_limb_count];
+ limb_type m_limbs;
+
+public:
+ //
+ // Helper functions for getting at our internal data, and manipulating storage:
+ //
+ unsigned size()const { return m_limbs; }
+ limb_pointer limbs() { return m_data; }
+ const_limb_pointer limbs()const { return m_data; }
+ bool sign()const { return false; }
+ void sign(bool b) { if(b) negate(); }
+ void resize(unsigned new_size)
+ {
+ m_limbs = (std::min)(new_size, internal_limb_count);
+ }
+ void normalize()
+ {
+ limb_pointer p = limbs();
+ while((m_limbs-1) && !p[m_limbs - 1])--m_limbs;
+ }
+
+ cpp_int_base() : m_limbs(1)
+ {
+ *limbs() = 0;
+ }
+ cpp_int_base(const cpp_int_base& o) : m_limbs(0)
+ {
+ resize(o.size());
+ std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
+ }
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ cpp_int_base(cpp_int_base&& o) : m_limbs(o.m_limbs)
+ {
+ std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
+ }
+#endif
+ ~cpp_int_base() {}
+ void assign(const cpp_int_base& o)
+ {
+ if(this != &o)
+ {
+ resize(o.size());
+ std::memcpy(limbs(), o.limbs(), size() * sizeof(limb_type));
+ }
+ }
+ void negate()
+ {
+ // Not so much a negate as a complement - this gets called when subtraction
+ // would result in a "negative" number:
+ unsigned i;
+ for(i = m_limbs; i < internal_limb_count; ++i)
+ m_data[i] = 0;
+ m_limbs = internal_limb_count;
+ for(i = 0; i < internal_limb_count; ++i)
+ m_data[i] = ~m_data[i];
+ normalize();
+ increment(static_cast<cpp_int_backend<MinBits, false, void>& >(*this));
+ }
+ bool isneg()const
+ {
+ return false;
+ }
+ void do_swap(cpp_int_base& o)
+ {
+ for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i)
+ std::swap(m_data[i], o.m_data[i]);
+ std::swap(m_limbs, o.m_limbs);
+ }
+};
+
+template <unsigned MinBits, bool Signed, class Allocator>
+struct cpp_int_backend : public cpp_int_base<MinBits, Signed, Allocator>
+{
+public:
+ typedef mpl::list<signed_limb_type, signed_double_limb_type> signed_types;
+ typedef mpl::list<limb_type, double_limb_type> unsigned_types;
+ typedef mpl::list<long double> float_types;
+
+ cpp_int_backend(){}
+ cpp_int_backend(const cpp_int_backend& o) : cpp_int_base(o) {}
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ cpp_int_backend(cpp_int_backend&& o) : cpp_int_base(o) {}
+#endif
+ cpp_int_backend& operator = (const cpp_int_backend& o)
+ {
+ this->assign(o);
       return *this;
    }
    cpp_int_backend& operator = (limb_type i)
    {
- m_limbs = 1;
- *limbs() = i;
- m_sign = false;
+ this->resize(1);
+ *this->limbs() = i;
+ this->sign(false);
       return *this;
    }
    cpp_int_backend& operator = (signed_limb_type i)
    {
- m_limbs = 1;
- *limbs() = static_cast<limb_type>(std::abs(i));
- m_sign = i < 0;
+ this->resize(1);
+ *this->limbs() = static_cast<limb_type>(std::abs(i));
+ this->sign(i < 0);
       return *this;
    }
    cpp_int_backend& operator = (double_limb_type i)
@@ -161,25 +391,27 @@
       limb_pointer p = limbs();
       *p = static_cast<limb_type>(i);
       p[1] = static_cast<limb_type>(i >> limb_bits);
- m_limbs = p[1] ? 2 : 1;
- m_sign = false;
+ this->resize(p[1] ? 2 : 1);
+ this->sign(false);
       return *this;
    }
    cpp_int_backend& operator = (signed_double_limb_type i)
    {
       BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
       BOOST_STATIC_ASSERT(internal_limb_count >= 2);
+ bool s = false;
       if(i < 0)
       {
- m_sign = true;
+ s = true;
          i = -i;
       }
       else
- m_sign = false;
- limb_pointer p = limbs();
+ this->sign(false);
+ limb_pointer p = this->limbs();
       *p = static_cast<limb_type>(i);
       p[1] = static_cast<limb_type>(i >> limb_bits);
- m_limbs = p[1] ? 2 : 1;
+ resize(p[1] ? 2 : 1);
+ this->sign(s);
       return *this;
    }
 
@@ -329,10 +561,7 @@
    }
    void swap(cpp_int_backend& o)
    {
- std::swap(m_data, o.m_data);
- std::swap(m_sign, o.m_sign);
- std::swap(m_internal, o.m_internal);
- std::swap(m_limbs, o.m_limbs);
+ this->do_swap(o);
    }
    std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
    {
@@ -347,6 +576,8 @@
 
       if(base == 8 || base == 16)
       {
+ if(this->sign())
+ BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported."));
          limb_type shift = base == 8 ? 3 : 4;
          limb_type mask = static_cast<limb_type>((1u << shift) - 1);
          cpp_int_backend t(*this);
@@ -428,41 +659,27 @@
       }
       return result;
    }
- void negate()
- {
- m_sign = !m_sign;
- // Check for zero value:
- if(m_sign && (m_limbs == 1))
- {
- if(limbs()[0] == 0)
- m_sign = false;
- }
- }
- bool isneg()const
- {
- return m_sign;
- }
    int compare(const cpp_int_backend& o)const
    {
- if(m_sign != o.m_sign)
- return m_sign ? -1 : 1;
+ if(sign() != o.sign())
+ return sign() ? -1 : 1;
       int result = 0;
       // Only do the compare if the same sign:
       result = compare_unsigned(o);
 
- if(m_sign)
+ if(sign())
          result = -result;
       return result;
    }
    int compare_unsigned(const cpp_int_backend& o)const
    {
- if(m_limbs != o.m_limbs)
+ if(size() != o.size())
       {
- return m_limbs > o.m_limbs ? 1 : -1;
+ return size() > o.size() ? 1 : -1;
       }
       const_limb_pointer pa = limbs();
       const_limb_pointer pb = o.limbs();
- for(int i = m_limbs - 1; i >= 0; --i)
+ for(int i = size() - 1; i >= 0; --i)
       {
          if(pa[i] != pb[i])
             return pa[i] > pb[i] ? 1 : -1;
@@ -479,23 +696,23 @@
    }
 };
 
-template <unsigned InternalLimbs, class Allocator>
-const unsigned cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
-template <unsigned InternalLimbs, class Allocator>
-const limb_type cpp_int_backend<InternalLimbs, Allocator>::max_limb_value;
-template <unsigned InternalLimbs, class Allocator>
-const limb_type cpp_int_backend<InternalLimbs, Allocator>::sign_bit_mask;
-template <unsigned InternalLimbs, class Allocator>
-const unsigned cpp_int_backend<InternalLimbs, Allocator>::internal_limb_count;
+template <unsigned MinBits, bool Signed, class Allocator>
+const unsigned cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
+template <unsigned MinBits, bool Signed, class Allocator>
+const limb_type cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value;
+template <unsigned MinBits, bool Signed, class Allocator>
+const limb_type cpp_int_backend<MinBits, Signed, Allocator>::sign_bit_mask;
+template <unsigned MinBits, bool Signed, class Allocator>
+const unsigned cpp_int_backend<MinBits, Signed, Allocator>::internal_limb_count;
 
 
-template <unsigned InternalLimbs, class Allocator>
-inline void add(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void add(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o)
 {
    add(result, result, o);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void add_unsigned(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void add_unsigned(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    using std::swap;
 
@@ -511,10 +728,10 @@
       return;
    }
    result.resize(x);
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer pa = a.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer pb = b.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr_end = pr + m;
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer pa = a.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer pb = b.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr_end = pr + m;
 
    if(a.size() < b.size())
       swap(pa, pb);
@@ -524,7 +741,7 @@
    {
       carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb);
       *pr = static_cast<limb_type>(carry);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
       ++pr, ++pa, ++pb;
    }
    pr_end += x - m;
@@ -539,19 +756,21 @@
       }
       carry += static_cast<double_limb_type>(*pa);
       *pr = static_cast<limb_type>(carry);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
       ++pr, ++pa;
    }
    if(carry)
    {
       result.resize(x + 1);
       // We overflowed, need to add one more limb:
- result.limbs()[x] = static_cast<limb_type>(carry);
+ if(cpp_int_backend<MinBits, Signed, Allocator>::variable || (result.size() > x))
+ result.limbs()[x] = static_cast<limb_type>(carry);
    }
+ result.normalize();
    result.sign(a.sign());
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void add(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void add(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    if(a.sign() != b.sign())
    {
@@ -561,22 +780,31 @@
    add_unsigned(result, a, b);
 }
 
-template <unsigned InternalLimbs, class Allocator>
-inline void add_unsigned(cpp_int_backend<InternalLimbs, Allocator>& result, const limb_type& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void add_unsigned(cpp_int_backend<MinBits, Signed, Allocator>& result, const limb_type& o)
 {
    // Addition using modular arithmatic.
    // Nothing fancy, just let uintmax_t take the strain:
    double_limb_type carry = o;
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
    for(unsigned i = 0; carry && (i < result.size()); ++i)
    {
       carry += static_cast<double_limb_type>(pr[i]);
       pr[i] = static_cast<limb_type>(carry);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
    }
+ if(carry)
+ {
+ unsigned x = result.size();
+ result.resize(x + 1);
+ // We overflowed, need to add one more limb:
+ if(cpp_int_backend<MinBits, Signed, Allocator>::variable || (result.size() > x))
+ result.limbs()[x] = static_cast<limb_type>(carry);
+ }
+ result.normalize();
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void add(cpp_int_backend<InternalLimbs, Allocator>& result, const limb_type& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void add(cpp_int_backend<MinBits, Signed, Allocator>& result, const limb_type& o)
 {
    if(result.sign())
    {
@@ -585,8 +813,8 @@
    else
       add_unsigned(result, o);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void add(cpp_int_backend<InternalLimbs, Allocator>& result, const signed_limb_type& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void add(cpp_int_backend<MinBits, Signed, Allocator>& result, const signed_limb_type& o)
 {
    if(o < 0)
       subtract(result, static_cast<limb_type>(-o));
@@ -594,13 +822,13 @@
       add(result, static_cast<limb_type>(o));
 }
 
-template <unsigned InternalLimbs, class Allocator>
-inline void subtract_unsigned(cpp_int_backend<InternalLimbs, Allocator>& result, const limb_type& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void subtract_unsigned(cpp_int_backend<MinBits, Signed, Allocator>& result, const limb_type& o)
 {
    // Subtract one limb.
    // Nothing fancy, just let uintmax_t take the strain:
- BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(cpp_int_backend<InternalLimbs, Allocator>::max_limb_value) + 1);
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer p = result.limbs();
+ BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value) + 1);
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer p = result.limbs();
    if(*p > o)
    {
       *p -= o;
@@ -616,24 +844,23 @@
       ++p;
       while(!*p)
       {
- *p = cpp_int_backend<InternalLimbs, Allocator>::max_limb_value;
+ *p = cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value;
          ++p;
       }
       --*p;
- if(!result.limbs()[result.size() - 1])
- result.resize(result.size() - 1);
+ result.normalize();
    }
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void subtract(cpp_int_backend<InternalLimbs, Allocator>& result, const limb_type& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void subtract(cpp_int_backend<MinBits, Signed, Allocator>& result, const limb_type& o)
 {
    if(result.sign())
       add_unsigned(result, o);
    else
       subtract_unsigned(result, o);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void subtract(cpp_int_backend<InternalLimbs, Allocator>& result, const signed_limb_type& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void subtract(cpp_int_backend<MinBits, Signed, Allocator>& result, const signed_limb_type& o)
 {
    if(o)
    {
@@ -643,35 +870,35 @@
          subtract(result, static_cast<limb_type>(o));
    }
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void increment(cpp_int_backend<InternalLimbs, Allocator>& result)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void increment(cpp_int_backend<MinBits, Signed, Allocator>& result)
 {
    static const limb_type one = 1;
- if(!result.sign() && (result.limbs()[0] < cpp_int_backend<InternalLimbs, Allocator>::max_limb_value))
+ if(!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value))
       ++result.limbs()[0];
    else if(result.sign() && result.limbs()[0])
       --result.limbs()[0];
    else
       add(result, one);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void decrement(cpp_int_backend<InternalLimbs, Allocator>& result)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void decrement(cpp_int_backend<MinBits, Signed, Allocator>& result)
 {
    static const limb_type one = 1;
    if(!result.sign() && result.limbs()[0])
       --result.limbs()[0];
- else if(result.sign() && (result.limbs()[0] < cpp_int_backend<InternalLimbs, Allocator>::max_limb_value))
+ else if(result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value))
       ++result.limbs()[0];
    else
       subtract(result, one);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void subtract(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void subtract(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o)
 {
    subtract(result, result, o);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void subtract_unsigned(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void subtract_unsigned(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    using std::swap;
 
@@ -695,26 +922,11 @@
       result = al - bl;
       result.sign(s);
       return;
- }/*
- else if(m == 1)
- {
- if(b.size() == 1)
- {
- result = a;
- subtract_unsigned(result, *b.limbs());
- }
- else
- {
- result = b;
- subtract_unsigned(result, *a.limbs());
- result.negate();
- }
- return;
- }*/
+ }
    result.resize(x);
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer pa = a.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer pb = b.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer pa = a.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer pb = b.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
    bool swapped = false;
    int c = a.compare_unsigned(b);
    if(c < 0)
@@ -734,7 +946,7 @@
    {
       borrow = static_cast<double_limb_type>(pa[i]) - static_cast<double_limb_type>(pb[i]) - borrow;
       pr[i] = static_cast<limb_type>(borrow);
- borrow = (borrow >> cpp_int_backend<InternalLimbs, Allocator>::limb_bits) & 1u;
+ borrow = (borrow >> cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) & 1u;
       ++i;
    }
    // Now where only a has digits, only as long as we've borrowed:
@@ -742,7 +954,7 @@
    {
       borrow = static_cast<double_limb_type>(pa[i]) - borrow;
       pr[i] = static_cast<limb_type>(borrow);
- borrow = (borrow >> cpp_int_backend<InternalLimbs, Allocator>::limb_bits) & 1u;
+ borrow = (borrow >> cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) & 1u;
       ++i;
    }
    // Any remaining digits are the same as those in pa:
@@ -753,18 +965,13 @@
    //
    // We may have lost digits, if so update limb usage count:
    //
- i = result.size() - 1;
- while(!pr[i] && i)
- {
- --i;
- }
- result.resize(i + 1);
+ result.normalize();
    result.sign(a.sign());
    if(swapped)
       result.negate();
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void subtract(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void subtract(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    if(a.sign() != b.sign())
    {
@@ -773,8 +980,8 @@
    }
    subtract_unsigned(result, a, b);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void multiply(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void multiply(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    // Very simple long multiplication, only usable for small numbers of limb_type's
    // but that's the typical use case for this type anyway:
@@ -783,8 +990,8 @@
    //
    unsigned as = a.size();
    unsigned bs = b.size();
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer pa = a.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer pb = b.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer pa = a.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer pb = b.limbs();
    if(as == 1)
    {
       bool s = b.sign() != a.sign();
@@ -813,55 +1020,50 @@
 
    if(&result == &a)
    {
- cpp_int_backend<InternalLimbs, Allocator> t(a);
+ cpp_int_backend<MinBits, Signed, Allocator> t(a);
       multiply(result, t, b);
       return;
    }
    if(&result == &b)
    {
- cpp_int_backend<InternalLimbs, Allocator> t(b);
+ cpp_int_backend<MinBits, Signed, Allocator> t(b);
       multiply(result, a, t);
       return;
    }
 
    result.resize(as + bs);
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
 
    double_limb_type carry = 0;
    std::memset(pr, 0, (as + bs) * sizeof(limb_type));
+ unsigned inner_limit = result.size() - as;
    for(unsigned i = 0; i < as; ++i)
    {
- for(unsigned j = 0; j < bs; ++j)
+ for(unsigned j = 0; j < inner_limit; ++j)
       {
+ BOOST_ASSERT(i+j < result.size());
          carry += static_cast<double_limb_type>(pa[i]) * static_cast<double_limb_type>(pb[j]);
          carry += pr[i + j];
          pr[i + j] = static_cast<limb_type>(carry);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
       }
- pr[i + bs] = static_cast<limb_type>(carry);
+ if(cpp_int_backend<MinBits, Signed, Allocator>::variable || (i + bs < result.size()))
+ pr[i + bs] = static_cast<limb_type>(carry);
       carry = 0;
    }
- //
- // We may not have filled all the digits, if so update limb usage count:
- //
- unsigned i = result.size() - 1;
- while(!pr[i] && i)
- {
- --i;
- }
- result.resize(i + 1);
+ result.normalize();
    //
    // Set the sign of the result:
    //
    result.sign(a.sign() != b.sign());
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void multiply(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void multiply(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a)
 {
     multiply(result, result, a);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void multiply(cpp_int_backend<InternalLimbs, Allocator>& result, cpp_int_backend<InternalLimbs, Allocator>& a, const limb_type& val)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void multiply(cpp_int_backend<MinBits, Signed, Allocator>& result, cpp_int_backend<MinBits, Signed, Allocator>& a, const limb_type& val)
 {
    if(!val)
    {
@@ -869,29 +1071,33 @@
       return;
    }
    double_limb_type carry = 0;
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer p = result.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pe = result.limbs() + result.size();
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pa = a.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer p = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pe = result.limbs() + result.size();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pa = a.limbs();
    while(p != pe)
    {
       carry += static_cast<double_limb_type>(*pa * static_cast<double_limb_type>(val));
       *p = static_cast<limb_type>(carry);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
       ++p, ++pa;
    }
    if(carry)
    {
- result.resize(result.size() + 1);
- result.limbs()[result.size() - 1] = static_cast<limb_type>(carry);
+ unsigned i = result.size();
+ result.resize(i + 1);
+ if(cpp_int_backend<MinBits, Signed, Allocator>::variable || (result.size() > i))
+ result.limbs()[i] = static_cast<limb_type>(carry);
    }
+ if(!cpp_int_backend<MinBits, Signed, Allocator>::variable)
+ result.normalize();
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void multiply(cpp_int_backend<InternalLimbs, Allocator>& result, const limb_type& val)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void multiply(cpp_int_backend<MinBits, Signed, Allocator>& result, const limb_type& val)
 {
    multiply(result, result, val);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void multiply(cpp_int_backend<InternalLimbs, Allocator>& result, cpp_int_backend<InternalLimbs, Allocator>& a, const signed_limb_type& val)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void multiply(cpp_int_backend<MinBits, Signed, Allocator>& result, cpp_int_backend<MinBits, Signed, Allocator>& a, const signed_limb_type& val)
 {
    if(val > 0)
       multiply(result, a, static_cast<limb_type>(val));
@@ -901,23 +1107,23 @@
       result.negate();
    }
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void multiply(cpp_int_backend<InternalLimbs, Allocator>& result, const signed_limb_type& val)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void multiply(cpp_int_backend<MinBits, Signed, Allocator>& result, const signed_limb_type& val)
 {
    multiply(result, result, val);
 }
-template <unsigned InternalLimbs, class Allocator>
-void divide_unsigned_helper(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& x, const cpp_int_backend<InternalLimbs, Allocator>& y, cpp_int_backend<InternalLimbs, Allocator>& r)
+template <unsigned MinBits, bool Signed, class Allocator>
+void divide_unsigned_helper(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& x, const cpp_int_backend<MinBits, Signed, Allocator>& y, cpp_int_backend<MinBits, Signed, Allocator>& r)
 {
    if((&result == &x) || (&r == &x))
    {
- cpp_int_backend<InternalLimbs, Allocator> t(x);
+ cpp_int_backend<MinBits, Signed, Allocator> t(x);
       divide_unsigned_helper(result, t, y, r);
       return;
    }
    if((&result == &y) || (&r == &y))
    {
- cpp_int_backend<InternalLimbs, Allocator> t(y);
+ cpp_int_backend<MinBits, Signed, Allocator> t(y);
       divide_unsigned_helper(result, x, t, r);
       return;
    }
@@ -945,7 +1151,7 @@
 
    if(&result == &r)
    {
- cpp_int_backend<InternalLimbs, Allocator> rem;
+ cpp_int_backend<MinBits, Signed, Allocator> rem;
       divide_unsigned_helper(result, x, y, rem);
       r = rem;
       return;
@@ -967,8 +1173,8 @@
       return;
    }
 
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer px = x.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer py = y.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer px = x.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer py = y.limbs();
 
    limb_type r_order = x.size() - 1;
    if((r_order == 0) && (*px == 0))
@@ -995,7 +1201,7 @@
       }
    }
 
- cpp_int_backend<InternalLimbs, Allocator> t;
+ cpp_int_backend<MinBits, Signed, Allocator> t;
    bool r_neg = false;
 
    //
@@ -1010,9 +1216,9 @@
    else if(r_order == 1)
    {
       double_limb_type a, b;
- a = (static_cast<double_limb_type>(px[1]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits) | px[0];
+ a = (static_cast<double_limb_type>(px[1]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) | px[0];
       b = y_order > 1 ?
- (static_cast<double_limb_type>(py[1]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits) | py[0]
+ (static_cast<double_limb_type>(py[1]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) | py[0]
          : py[0];
       result = a / b;
       r = a % b;
@@ -1022,8 +1228,8 @@
    // prepare result:
    //
    result.resize(1 + r_order - y_order);
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer prem = r.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer prem = r.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
    for(unsigned i = 1; i < 1 + r_order - y_order; ++i)
       pr[i] = 0;
    bool first_pass = true;
@@ -1041,10 +1247,10 @@
       if((prem[r_order] <= py[y_order]) && (r_order > 0))
       {
          double_limb_type a, b, v;
- a = (static_cast<double_limb_type>(prem[r_order]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits) | prem[r_order - 1];
+ a = (static_cast<double_limb_type>(prem[r_order]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) | prem[r_order - 1];
          b = py[y_order];
          v = a / b;
- if(v > cpp_int_backend<InternalLimbs, Allocator>::max_limb_value)
+ if(v > cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value)
             guess = 1;
          else
          {
@@ -1059,8 +1265,8 @@
       else
       {
          double_limb_type a, b, v;
- a = (static_cast<double_limb_type>(prem[r_order]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits) | prem[r_order - 1];
- b = (y_order > 0) ? (static_cast<double_limb_type>(py[y_order]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits) | py[y_order - 1] : (static_cast<double_limb_type>(py[y_order]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits);
+ a = (static_cast<double_limb_type>(prem[r_order]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) | prem[r_order - 1];
+ b = (y_order > 0) ? (static_cast<double_limb_type>(py[y_order]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) | py[y_order - 1] : (static_cast<double_limb_type>(py[y_order]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits);
          v = a / b;
          guess = static_cast<limb_type>(v);
       }
@@ -1082,7 +1288,7 @@
             subtract(result, t);
          }
       }
- else if(cpp_int_backend<InternalLimbs, Allocator>::max_limb_value - pr[shift] > guess)
+ else if(cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value - pr[shift] > guess)
          pr[shift] += guess;
       else
       {
@@ -1098,14 +1304,14 @@
       //
       double_limb_type carry = 0;
       t.resize(y.size() + shift + 1);
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pt = t.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pt = t.limbs();
       for(unsigned i = 0; i < shift; ++i)
          pt[i] = 0;
       for(unsigned i = 0; i < y.size(); ++i)
       {
          carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
          pt[i + shift] = static_cast<limb_type>(carry);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
       }
       if(carry)
       {
@@ -1156,19 +1362,19 @@
    BOOST_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed
 }
 
-template <unsigned InternalLimbs, class Allocator>
-void divide_unsigned_helper(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& x, limb_type y, cpp_int_backend<InternalLimbs, Allocator>& r)
+template <unsigned MinBits, bool Signed, class Allocator>
+void divide_unsigned_helper(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& x, limb_type y, cpp_int_backend<MinBits, Signed, Allocator>& r)
 {
    if((&result == &x) || (&r == &x))
    {
- cpp_int_backend<InternalLimbs, Allocator> t(x);
+ cpp_int_backend<MinBits, Signed, Allocator> t(x);
       divide_unsigned_helper(result, t, y, r);
       return;
    }
 
    if(&result == &r)
    {
- cpp_int_backend<InternalLimbs, Allocator> rem;
+ cpp_int_backend<MinBits, Signed, Allocator> rem;
       divide_unsigned_helper(result, x, y, rem);
       r = rem;
       return;
@@ -1192,7 +1398,7 @@
    //
    r = x;
    r.sign(false);
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = r.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = r.limbs();
 
    if((r_order == 0) && (*pr == 0))
    {
@@ -1223,7 +1429,7 @@
    else if(r_order == 1)
    {
       double_limb_type a;
- a = (static_cast<double_limb_type>(pr[r_order]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits) | pr[0];
+ a = (static_cast<double_limb_type>(pr[r_order]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) | pr[0];
       result = a / y;
       result.sign(x.sign());
       r = a % y;
@@ -1232,7 +1438,7 @@
    }
 
    result.resize(r_order + 1);
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pres = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pres = result.limbs();
    pres[r_order] = 0; // just in case we don't set the most significant limb below.
 
    do
@@ -1243,7 +1449,7 @@
       if((pr[r_order] < y) && r_order)
       {
          double_limb_type a, b;
- a = (static_cast<double_limb_type>(pr[r_order]) << cpp_int_backend<InternalLimbs, Allocator>::limb_bits) | pr[r_order - 1];
+ a = (static_cast<double_limb_type>(pr[r_order]) << cpp_int_backend<MinBits, Signed, Allocator>::limb_bits) | pr[r_order - 1];
          b = a % y;
          r.resize(r.size() - 1);
          --r_order;
@@ -1269,90 +1475,90 @@
    BOOST_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
 }
 
-template <unsigned InternalLimbs, class Allocator>
-inline void divide(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void divide(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
- cpp_int_backend<InternalLimbs, Allocator> r;
+ cpp_int_backend<MinBits, Signed, Allocator> r;
    divide_unsigned_helper(result, a, b, r);
    result.sign(a.sign() != b.sign());
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void divide(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, limb_type& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void divide(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, limb_type& b)
 {
- cpp_int_backend<InternalLimbs, Allocator> r;
+ cpp_int_backend<MinBits, Signed, Allocator> r;
    divide_unsigned_helper(result, a, b, r);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void divide(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, signed_limb_type& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void divide(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, signed_limb_type& b)
 {
- cpp_int_backend<InternalLimbs, Allocator> r;
+ cpp_int_backend<MinBits, Signed, Allocator> r;
    divide_unsigned_helper(result, a, std::abs(b), r);
    if(b < 0)
       result.negate();
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void divide(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void divide(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    // There is no in place divide:
- cpp_int_backend<InternalLimbs, Allocator> a(result);
+ cpp_int_backend<MinBits, Signed, Allocator> a(result);
    divide(result, a, b);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void divide(cpp_int_backend<InternalLimbs, Allocator>& result, limb_type b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void divide(cpp_int_backend<MinBits, Signed, Allocator>& result, limb_type b)
 {
    // There is no in place divide:
- cpp_int_backend<InternalLimbs, Allocator> a(result);
+ cpp_int_backend<MinBits, Signed, Allocator> a(result);
    divide(result, a, b);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void divide(cpp_int_backend<InternalLimbs, Allocator>& result, signed_limb_type b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void divide(cpp_int_backend<MinBits, Signed, Allocator>& result, signed_limb_type b)
 {
    // There is no in place divide:
- cpp_int_backend<InternalLimbs, Allocator> a(result);
+ cpp_int_backend<MinBits, Signed, Allocator> a(result);
    divide(result, a, b);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void modulus(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void modulus(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
- cpp_int_backend<InternalLimbs, Allocator> r;
+ cpp_int_backend<MinBits, Signed, Allocator> r;
    divide_unsigned_helper(r, a, b, result);
    result.sign(a.sign());
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void modulus(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, limb_type b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void modulus(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, limb_type b)
 {
- cpp_int_backend<InternalLimbs, Allocator> r;
+ cpp_int_backend<MinBits, Signed, Allocator> r;
    divide_unsigned_helper(r, a, b, result);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void modulus(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, signed_limb_type b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void modulus(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, signed_limb_type b)
 {
- cpp_int_backend<InternalLimbs, Allocator> r;
+ cpp_int_backend<MinBits, Signed, Allocator> r;
    divide_unsigned_helper(r, a, static_cast<limb_type>(std::abs(b)), result);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void modulus(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void modulus(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    // There is no in place divide:
- cpp_int_backend<InternalLimbs, Allocator> a(result);
+ cpp_int_backend<MinBits, Signed, Allocator> a(result);
    modulus(result, a, b);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void modulus(cpp_int_backend<InternalLimbs, Allocator>& result, limb_type b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void modulus(cpp_int_backend<MinBits, Signed, Allocator>& result, limb_type b)
 {
    // There is no in place divide:
- cpp_int_backend<InternalLimbs, Allocator> a(result);
+ cpp_int_backend<MinBits, Signed, Allocator> a(result);
    modulus(result, a, b);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void modulus(cpp_int_backend<InternalLimbs, Allocator>& result, signed_limb_type b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void modulus(cpp_int_backend<MinBits, Signed, Allocator>& result, signed_limb_type b)
 {
    // There is no in place divide:
- cpp_int_backend<InternalLimbs, Allocator> a(result);
+ cpp_int_backend<MinBits, Signed, Allocator> a(result);
    modulus(result, a, b);
 }
-template <unsigned InternalLimbs, class Allocator, class Op>
-void bitwise_op(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o, Op op)
+template <unsigned MinBits, bool Signed, class Allocator, class Op>
+void bitwise_op(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o, Op op)
 {
    //
    // There are 4 cases:
@@ -1371,8 +1577,8 @@
    unsigned m, x;
    minmax(rs, os, m, x);
    result.resize(x);
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer po = o.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer po = o.limbs();
    for(unsigned i = rs; i < x; ++i)
       pr[i] = 0;
 
@@ -1395,13 +1601,13 @@
          {
             carry += static_cast<double_limb_type>(~po[i]);
             pr[i] = op(pr[i], static_cast<limb_type>(carry));
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
          }
          for(unsigned i = os; i < x; ++i)
          {
             carry += static_cast<double_limb_type>(~limb_type(0));
             pr[i] = op(pr[i], static_cast<limb_type>(carry));
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
          }
          // Set the overflow into the "extra" limb:
          carry += static_cast<double_limb_type>(~limb_type(0));
@@ -1418,13 +1624,13 @@
          {
             carry += static_cast<double_limb_type>(~pr[i]);
             pr[i] = op(static_cast<limb_type>(carry), po[i]);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
          }
          for(unsigned i = os; i < x; ++i)
          {
             carry += static_cast<double_limb_type>(~pr[i]);
             pr[i] = op(static_cast<limb_type>(carry), limb_type(0));
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
          }
          // Set the overflow into the "extra" limb:
          carry += static_cast<double_limb_type>(~limb_type(0));
@@ -1440,16 +1646,16 @@
             r_carry += static_cast<double_limb_type>(~pr[i]);
             o_carry += static_cast<double_limb_type>(~po[i]);
             pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
- r_carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
- o_carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ r_carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
+ o_carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
          }
          for(unsigned i = os; i < x; ++i)
          {
             r_carry += static_cast<double_limb_type>(~pr[i]);
             o_carry += static_cast<double_limb_type>(~limb_type(0));
             pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
- r_carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
- o_carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ r_carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
+ o_carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
          }
          // Set the overflow into the "extra" limb:
          r_carry += static_cast<double_limb_type>(~limb_type(0));
@@ -1468,106 +1674,179 @@
       {
          carry += static_cast<double_limb_type>(~pr[i]);
          pr[i] = static_cast<limb_type>(carry);
- carry >>= cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
       }
    }
    else
       result.sign(false);
- //
- // Strip leading zeros:
- //
- while((result.size() > 1) && (result.limbs()[result.size()-1] == 0))
- result.resize(result.size()-1);
+
+ result.normalize();
 }
 
 struct bit_and{ limb_type operator()(limb_type a, limb_type b)const{ return a & b; } };
 struct bit_or{ limb_type operator()(limb_type a, limb_type b)const{ return a | b; } };
 struct bit_xor{ limb_type operator()(limb_type a, limb_type b)const{ return a ^ b; } };
 
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_and(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_and(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o)
 {
    bitwise_op(result, o, bit_and());
 }
 #if 0
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_and(cpp_int_backend<InternalLimbs, Allocator>& result, limb_type o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_and(cpp_int_backend<MinBits, Signed, Allocator>& result, limb_type o)
 {
- result.data()[cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1] &= o;
- for(typename cpp_int_backend<InternalLimbs, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1; ++i)
+ result.data()[cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1] &= o;
+ for(typename cpp_int_backend<MinBits, Signed, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1; ++i)
       result.data()[i] = 0;
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_and(cpp_int_backend<InternalLimbs, Allocator>& result, signed_limb_type o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_and(cpp_int_backend<MinBits, Signed, Allocator>& result, signed_limb_type o)
 {
- result.data()[cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1] &= o;
- limb_type mask = o < 0 ? cpp_int_backend<InternalLimbs, Allocator>::max_limb_value : 0;
- for(typename cpp_int_backend<InternalLimbs, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1; ++i)
+ result.data()[cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1] &= o;
+ limb_type mask = o < 0 ? cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value : 0;
+ for(typename cpp_int_backend<MinBits, Signed, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1; ++i)
       result.data()[i] &= mask;
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_or(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_or(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o)
 {
- for(typename cpp_int_backend<InternalLimbs, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<InternalLimbs, Allocator>::limb_count; ++i)
+ for(typename cpp_int_backend<MinBits, Signed, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<MinBits, Signed, Allocator>::limb_count; ++i)
       result.data()[i] |= o.data()[i];
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_or(cpp_int_backend<InternalLimbs, Allocator>& result, limb_type o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_or(cpp_int_backend<MinBits, Signed, Allocator>& result, limb_type o)
 {
- result.data()[cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1] |= o;
+ result.data()[cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1] |= o;
 }
 #endif
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_or(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_or(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o)
 {
    bitwise_op(result, o, bit_or());
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_xor(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_xor(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o)
 {
    bitwise_op(result, o, bit_xor());
 }
 #if 0
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_xor(cpp_int_backend<InternalLimbs, Allocator>& result, limb_type o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_xor(cpp_int_backend<MinBits, Signed, Allocator>& result, limb_type o)
 {
- result.data()[cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1] ^= o;
+ result.data()[cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1] ^= o;
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void bitwise_xor(cpp_int_backend<InternalLimbs, Allocator>& result, signed_limb_type o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void bitwise_xor(cpp_int_backend<MinBits, Signed, Allocator>& result, signed_limb_type o)
 {
- result.data()[cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1] ^= o;
- limb_type mask = o < 0 ? cpp_int_backend<InternalLimbs, Allocator>::max_limb_value : 0;
- for(typename cpp_int_backend<InternalLimbs, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<InternalLimbs, Allocator>::limb_count - 1; ++i)
+ result.data()[cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1] ^= o;
+ limb_type mask = o < 0 ? cpp_int_backend<MinBits, Signed, Allocator>::max_limb_value : 0;
+ for(typename cpp_int_backend<MinBits, Signed, Allocator>::data_type::size_type i = 0; i < cpp_int_backend<MinBits, Signed, Allocator>::limb_count - 1; ++i)
       result.data()[i] ^= mask;
 }
 #endif
-template <unsigned InternalLimbs, class Allocator>
-inline void complement(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& o)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void complement(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& o)
 {
    // Increment and negate:
    result = o;
    increment(result);
    result.negate();
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void left_shift(cpp_int_backend<InternalLimbs, Allocator>& result, double_limb_type s)
+template <unsigned MinBits, bool Signed>
+inline void left_shift(cpp_int_backend<MinBits, Signed, void>& result, double_limb_type s)
 {
    if(!s)
       return;
 
- limb_type offset = static_cast<limb_type>(s / cpp_int_backend<InternalLimbs, Allocator>::limb_bits);
- limb_type shift = static_cast<limb_type>(s % cpp_int_backend<InternalLimbs, Allocator>::limb_bits);
+ limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits, Signed, void>::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits, Signed, void>::limb_bits);
+
+ if(offset > cpp_int_backend<MinBits, Signed, void>::internal_limb_count)
+ {
+ result = static_cast<limb_type>(0);
+ return;
+ }
 
    unsigned ors = result.size();
    if((ors == 1) && (!*result.limbs()))
       return; // shifting zero yields zero.
    unsigned rs = ors;
- if(shift && (result.limbs()[rs - 1] >> (cpp_int_backend<InternalLimbs, Allocator>::limb_bits - shift)))
+ if(shift && (result.limbs()[rs - 1] >> (cpp_int_backend<MinBits, Signed, void>::limb_bits - shift)))
       ++rs; // Most significant limb will overflow when shifted
    rs += offset;
    result.resize(rs);
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
+ bool truncated = result.size() != rs;
+ if(truncated)
+ rs = result.size();
+ typename cpp_int_backend<MinBits, Signed, void>::limb_pointer pr = result.limbs();
+
+ unsigned i = 0;
+ if(shift)
+ {
+ // This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
+ i = 0;
+ if(!truncated)
+ {
+ if(rs > ors)
+ {
+ pr[rs - 1 - i] = pr[ors - 1 - i] >> (cpp_int_backend<MinBits, Signed, void>::limb_bits - shift);
+ --rs;
+ }
+ else
+ {
+ pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
+ if(ors > 1)
+ pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits, Signed, void>::limb_bits - shift);
+ ++i;
+ }
+ }
+ for(; ors > 1 + i; ++i)
+ {
+ pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
+ pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits, Signed, void>::limb_bits - shift);
+ }
+ if(ors >= 1 + i)
+ {
+ pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
+ ++i;
+ }
+ for(; i < rs; ++i)
+ pr[rs - 1 - i] = 0;
+ }
+ else
+ {
+ for(; i < ors; ++i)
+ pr[rs - 1 - i] = pr[ors - 1 - i];
+ for(; i < rs; ++i)
+ pr[rs - 1 - i] = 0;
+ }
+ //
+ // We may have shifted off the end and have leading zeros:
+ //
+ if(truncated)
+ {
+ result.normalize();
+ }
+}
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void left_shift(cpp_int_backend<MinBits, Signed, Allocator>& result, double_limb_type s)
+{
+ if(!s)
+ return;
+
+ limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits, Signed, Allocator>::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits, Signed, Allocator>::limb_bits);
+
+ unsigned ors = result.size();
+ if((ors == 1) && (!*result.limbs()))
+ return; // shifting zero yields zero.
+ unsigned rs = ors;
+ if(shift && (result.limbs()[rs - 1] >> (cpp_int_backend<MinBits, Signed, Allocator>::limb_bits - shift)))
+ ++rs; // Most significant limb will overflow when shifted
+ rs += offset;
+ result.resize(rs);
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
 
    unsigned i = 0;
    if(shift)
@@ -1576,20 +1855,20 @@
       i = 0;
       if(rs > ors)
       {
- pr[rs - 1 - i] = pr[ors - 1 - i] >> (cpp_int_backend<InternalLimbs, Allocator>::limb_bits - shift);
+ pr[rs - 1 - i] = pr[ors - 1 - i] >> (cpp_int_backend<MinBits, Signed, Allocator>::limb_bits - shift);
          --rs;
       }
       else
       {
          pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
          if(ors > 1)
- pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<InternalLimbs, Allocator>::limb_bits - shift);
+ pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits, Signed, Allocator>::limb_bits - shift);
          ++i;
       }
       for(; ors > 1 + i; ++i)
       {
          pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
- pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<InternalLimbs, Allocator>::limb_bits - shift);
+ pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits, Signed, Allocator>::limb_bits - shift);
       }
       if(ors >= 1 + i)
       {
@@ -1607,14 +1886,14 @@
          pr[rs - 1 - i] = 0;
    }
 }
-template <unsigned InternalLimbs, class Allocator>
-inline void right_shift(cpp_int_backend<InternalLimbs, Allocator>& result, double_limb_type s)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void right_shift(cpp_int_backend<MinBits, Signed, Allocator>& result, double_limb_type s)
 {
    if(!s)
       return;
 
- limb_type offset = static_cast<limb_type>(s / cpp_int_backend<InternalLimbs, Allocator>::limb_bits);
- limb_type shift = static_cast<limb_type>(s % cpp_int_backend<InternalLimbs, Allocator>::limb_bits);
+ limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits, Signed, Allocator>::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits, Signed, Allocator>::limb_bits);
    unsigned ors = result.size();
    unsigned rs = ors;
    if(offset >= rs)
@@ -1623,7 +1902,7 @@
       return;
    }
    rs -= offset;
- typename cpp_int_backend<InternalLimbs, Allocator>::limb_pointer pr = result.limbs();
+ typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pr = result.limbs();
    if((pr[ors - 1] >> shift) == 0)
       --rs;
    if(rs == 0)
@@ -1638,7 +1917,7 @@
       for(; i + offset + 1 < ors; ++i)
       {
          pr[i] = pr[i + offset] >> shift;
- pr[i] |= pr[i + offset + 1] << (cpp_int_backend<InternalLimbs, Allocator>::limb_bits - shift);
+ pr[i] |= pr[i + offset + 1] << (cpp_int_backend<MinBits, Signed, Allocator>::limb_bits - shift);
       }
       pr[i] = pr[i + offset] >> shift;
    }
@@ -1661,15 +1940,15 @@
    return ~--i;
 }
 
-template <class R, unsigned InternalLimbs, class Allocator>
-inline typename enable_if<is_integral<R>, void>::type convert_to(R* result, const cpp_int_backend<InternalLimbs, Allocator>& backend)
+template <class R, unsigned MinBits, bool Signed, class Allocator>
+inline typename enable_if<is_integral<R>, void>::type convert_to(R* result, const cpp_int_backend<MinBits, Signed, Allocator>& backend)
 {
    *result = static_cast<R>(backend.limbs()[0]);
- unsigned shift = cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ unsigned shift = cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
    for(unsigned i = 1; i < backend.size(); ++i)
    {
       *result += static_cast<R>(backend.limbs()[i]) << shift;
- shift += cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ shift += cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
       if(shift > static_cast<unsigned>(std::numeric_limits<R>::digits))
          break;
    }
@@ -1679,28 +1958,28 @@
    }
 }
 
-template <class R, unsigned InternalLimbs, class Allocator>
-inline typename enable_if<is_floating_point<R>, void>::type convert_to(R* result, const cpp_int_backend<InternalLimbs, Allocator>& backend)
+template <class R, unsigned MinBits, bool Signed, class Allocator>
+inline typename enable_if<is_floating_point<R>, void>::type convert_to(R* result, const cpp_int_backend<MinBits, Signed, Allocator>& backend)
 {
- typename cpp_int_backend<InternalLimbs, Allocator>::const_limb_pointer p = backend.limbs();
- unsigned shift = cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ typename cpp_int_backend<MinBits, Signed, Allocator>::const_limb_pointer p = backend.limbs();
+ unsigned shift = cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
    *result = static_cast<R>(*p);
    for(unsigned i = 1; i < backend.size(); ++i)
    {
       *result += static_cast<R>(std::ldexp(static_cast<long double>(p[i]), shift));
- shift += cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ shift += cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
    }
    if(backend.sign())
       *result = -*result;
 }
 
-template <unsigned InternalLimbs, class Allocator>
-inline bool is_zero(const cpp_int_backend<InternalLimbs, Allocator>& val)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline bool is_zero(const cpp_int_backend<MinBits, Signed, Allocator>& val)
 {
    return (val.size() == 1) && (val.limbs()[0] == 0);
 }
-template <unsigned InternalLimbs, class Allocator>
-inline int get_sign(const cpp_int_backend<InternalLimbs, Allocator>& val)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline int get_sign(const cpp_int_backend<MinBits, Signed, Allocator>& val)
 {
    return is_zero(val) ? 0 : val.sign() ? -1 : 1;
 }
@@ -1709,8 +1988,8 @@
 //
 // Get the location of the least-significant-bit:
 //
-template <unsigned InternalLimbs, class Allocator>
-inline unsigned get_lsb(const cpp_int_backend<InternalLimbs, Allocator>& a)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline unsigned get_lsb(const cpp_int_backend<MinBits, Signed, Allocator>& a)
 {
    BOOST_ASSERT(get_sign(a) != 0);
    
@@ -1731,17 +2010,17 @@
       ++result;
    }
 
- return result + index * cpp_int_backend<InternalLimbs, Allocator>::limb_bits;
+ return result + index * cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
 }
 
 }
 
-template <unsigned InternalLimbs, class Allocator>
-inline void eval_gcd(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void eval_gcd(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
    int shift;
 
- cpp_int_backend<InternalLimbs, Allocator> u(a), v(b);
+ cpp_int_backend<MinBits, Signed, Allocator> u(a), v(b);
 
    int s = get_sign(u);
 
@@ -1796,10 +2075,10 @@
    left_shift(result, shift);
 }
 
-template <unsigned InternalLimbs, class Allocator>
-inline void eval_lcm(cpp_int_backend<InternalLimbs, Allocator>& result, const cpp_int_backend<InternalLimbs, Allocator>& a, const cpp_int_backend<InternalLimbs, Allocator>& b)
+template <unsigned MinBits, bool Signed, class Allocator>
+inline void eval_lcm(cpp_int_backend<MinBits, Signed, Allocator>& result, const cpp_int_backend<MinBits, Signed, Allocator>& a, const cpp_int_backend<MinBits, Signed, Allocator>& b)
 {
- cpp_int_backend<InternalLimbs, Allocator> t;
+ cpp_int_backend<MinBits, Signed, Allocator> t;
    eval_gcd(t, a, b);
 
    if(is_zero(t))
@@ -1815,8 +2094,8 @@
       result.negate();
 }
 
-template <unsigned InternalLimbs, class Allocator>
-struct number_category<cpp_int_backend<InternalLimbs, Allocator> > : public mpl::int_<number_kind_integer>{};
+template <unsigned MinBits, bool Signed, class Allocator>
+struct number_category<cpp_int_backend<MinBits, Signed, Allocator> > : public mpl::int_<number_kind_integer>{};
 
 typedef mp_number<cpp_int_backend<> > cpp_int;
 typedef rational_adapter<cpp_int_backend<> > cpp_rational_backend;
@@ -1827,10 +2106,10 @@
 
 namespace std{
 
-template <unsigned InternalLimbs, class Allocator>
-class numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<InternalLimbs, Allocator> > >
+template <unsigned MinBits, bool Signed, class Allocator>
+class numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, Signed, Allocator> > >
 {
- typedef boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<InternalLimbs, Allocator> > number_type;
+ typedef boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, Signed, Allocator> > number_type;
 
 public:
    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
@@ -1877,6 +2156,165 @@
    BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
 };
 
+template <unsigned MinBits>
+class numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, true, void> > >
+{
+ typedef boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, true, void> > number_type;
+
+ struct inititializer
+ {
+ inititializer()
+ {
+ (std::numeric_limits<number_type>::max)();
+ (std::numeric_limits<number_type>::min)();
+ }
+ void do_nothing()const{}
+ };
+
+ static const inititializer init;
+
+public:
+ BOOST_STATIC_CONSTEXPR bool is_specialized = true;
+ //
+ // Largest and smallest numbers are bounded only by available memory, set
+ // to zero:
+ //
+ static number_type (min)() BOOST_MP_NOEXCEPT
+ {
+ return -(max)();
+ }
+ static number_type (max)() BOOST_MP_NOEXCEPT
+ {
+ typedef typename number_type::backend_type backend_type;
+ init.do_nothing();
+ static bool init = false;
+ static number_type val;
+ if(!init)
+ {
+ boost::multiprecision::limb_type l = ~static_cast<boost::multiprecision::limb_type>(0);
+ unsigned c = MinBits / backend_type::limb_bits + (MinBits % backend_type::limb_bits ? 1 : 0);
+ for(unsigned i = 0; i < c; ++i)
+ {
+ val <<= backend_type::limb_bits;
+ val |= l;
+ }
+ init = true;
+ }
+ return val;
+ }
+ static number_type lowest() BOOST_MP_NOEXCEPT { return (min)(); }
+ BOOST_STATIC_CONSTEXPR int digits = MinBits;
+ BOOST_STATIC_CONSTEXPR int digits10 = static_cast<int>(MinBits * 301L / 1000L);
+ BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
+ BOOST_STATIC_CONSTEXPR bool is_signed = true;
+ BOOST_STATIC_CONSTEXPR bool is_integer = true;
+ BOOST_STATIC_CONSTEXPR bool is_exact = true;
+ BOOST_STATIC_CONSTEXPR int radix = 2;
+ static number_type epsilon() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type round_error() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR int min_exponent = 0;
+ BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
+ BOOST_STATIC_CONSTEXPR int max_exponent = 0;
+ BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
+ BOOST_STATIC_CONSTEXPR bool has_infinity = false;
+ BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
+ BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
+ BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
+ BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
+ static number_type infinity() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type quiet_NaN() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type signaling_NaN() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type denorm_min() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
+ BOOST_STATIC_CONSTEXPR bool is_bounded = true;
+ BOOST_STATIC_CONSTEXPR bool is_modulo = true;
+ BOOST_STATIC_CONSTEXPR bool traps = false;
+ BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
+ BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
+};
+
+template <unsigned MinBits>
+const typename numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, true, void> > >::inititializer numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, true, void> > >::init;
+
+template <unsigned MinBits>
+class numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, false, void> > >
+{
+ typedef boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, false, void> > number_type;
+
+ struct inititializer
+ {
+ inititializer()
+ {
+ (std::numeric_limits<number_type>::max)();
+ }
+ void do_nothing()const{}
+ };
+
+ static const inititializer init;
+
+public:
+ BOOST_STATIC_CONSTEXPR bool is_specialized = true;
+ //
+ // Largest and smallest numbers are bounded only by available memory, set
+ // to zero:
+ //
+ static number_type (min)() BOOST_MP_NOEXCEPT
+ {
+ return number_type(0);
+ }
+ static number_type (max)() BOOST_MP_NOEXCEPT
+ {
+ typedef typename number_type::backend_type backend_type;
+ init.do_nothing();
+ static bool init = false;
+ static number_type val(0);
+ if(!init)
+ {
+ boost::multiprecision::limb_type l = ~static_cast<boost::multiprecision::limb_type>(0);
+ unsigned c = MinBits / backend_type::limb_bits + (MinBits % backend_type::limb_bits ? 1 : 0);
+ for(unsigned i = 0; i < c; ++i)
+ {
+ val <<= backend_type::limb_bits;
+ val |= l;
+ }
+ init = true;
+ }
+ return val;
+ }
+ static number_type lowest() BOOST_MP_NOEXCEPT { return (min)(); }
+ BOOST_STATIC_CONSTEXPR int digits = MinBits;
+ BOOST_STATIC_CONSTEXPR int digits10 = static_cast<int>(MinBits * 301L / 1000L);
+ BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
+ BOOST_STATIC_CONSTEXPR bool is_signed = false;
+ BOOST_STATIC_CONSTEXPR bool is_integer = true;
+ BOOST_STATIC_CONSTEXPR bool is_exact = true;
+ BOOST_STATIC_CONSTEXPR int radix = 2;
+ static number_type epsilon() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type round_error() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR int min_exponent = 0;
+ BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
+ BOOST_STATIC_CONSTEXPR int max_exponent = 0;
+ BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
+ BOOST_STATIC_CONSTEXPR bool has_infinity = false;
+ BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
+ BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
+ BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
+ BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
+ static number_type infinity() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type quiet_NaN() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type signaling_NaN() BOOST_MP_NOEXCEPT { return 0; }
+ static number_type denorm_min() BOOST_MP_NOEXCEPT { return 0; }
+ BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
+ BOOST_STATIC_CONSTEXPR bool is_bounded = true;
+ BOOST_STATIC_CONSTEXPR bool is_modulo = true;
+ BOOST_STATIC_CONSTEXPR bool traps = false;
+ BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
+ BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
+};
+
+template <unsigned MinBits>
+const typename numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, false, void> > >::inititializer numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<MinBits, false, void> > >::init;
+
 }
 
 #endif

Modified: sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp 2012-03-08 05:34:37 EST (Thu, 08 Mar 2012)
@@ -1047,6 +1047,8 @@
 #endif
 #ifdef TEST_CPP_INT
    test<boost::multiprecision::cpp_int>();
+ test<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<256, true, void> > >();
+ test<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<256, false, void> > >();
 #endif
 #ifdef TEST_CPP_INT_BR
    test<boost::multiprecision::cpp_rational>();

Modified: sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp 2012-03-08 05:34:37 EST (Thu, 08 Mar 2012)
@@ -51,10 +51,11 @@
    return val;
 }
 
-int main()
+template <class Number>
+void test()
 {
    using namespace boost::multiprecision;
- typedef cpp_int packed_type;
+ typedef Number test_type;
    unsigned last_error_count = 0;
    for(int i = 0; i < 1000; ++i)
    {
@@ -65,77 +66,77 @@
 
       int si = d.convert_to<int>();
 
- packed_type a1 = a.str();
- packed_type b1 = b.str();
- packed_type c1 = c.str();
- packed_type d1 = d.str();
+ test_type a1 = a.str();
+ test_type b1 = b.str();
+ test_type c1 = c.str();
+ test_type d1 = d.str();
 
       BOOST_CHECK_EQUAL(a.str(), a1.str());
       BOOST_CHECK_EQUAL(b.str(), b1.str());
       BOOST_CHECK_EQUAL(c.str(), c1.str());
       BOOST_CHECK_EQUAL(d.str(), d1.str());
- BOOST_CHECK_EQUAL(mpz_int(a+b).str(), packed_type(a1 + b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a-b).str(), packed_type(a1 - b1).str());
- BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)+b).str(), packed_type(packed_type(-a1) + b1).str());
- BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)-b).str(), packed_type(packed_type(-a1) - b1).str());
- BOOST_CHECK_EQUAL(mpz_int(c * d).str(), packed_type(c1 * d1).str());
- BOOST_CHECK_EQUAL(mpz_int(c * -d).str(), packed_type(c1 * -d1).str());
- BOOST_CHECK_EQUAL(mpz_int(-c * d).str(), packed_type(-c1 * d1).str());
- BOOST_CHECK_EQUAL(mpz_int(b * c).str(), packed_type(b1 * c1).str());
- BOOST_CHECK_EQUAL(mpz_int(a / b).str(), packed_type(a1 / b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a / -b).str(), packed_type(a1 / -b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a / b).str(), packed_type(-a1 / b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a / d).str(), packed_type(a1 / d1).str());
- BOOST_CHECK_EQUAL(mpz_int(a % b).str(), packed_type(a1 % b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a % -b).str(), packed_type(a1 % -b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a % b).str(), packed_type(-a1 % b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a % d).str(), packed_type(a1 % d1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a+b).str(), test_type(a1 + b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a-b).str(), test_type(a1 - b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)+b).str(), test_type(test_type(-a1) + b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)-b).str(), test_type(test_type(-a1) - b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(c * d).str(), test_type(c1 * d1).str());
+ BOOST_CHECK_EQUAL(mpz_int(c * -d).str(), test_type(c1 * -d1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-c * d).str(), test_type(-c1 * d1).str());
+ BOOST_CHECK_EQUAL(mpz_int(b * c).str(), test_type(b1 * c1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a / b).str(), test_type(a1 / b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a / -b).str(), test_type(a1 / -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a / b).str(), test_type(-a1 / b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a / d).str(), test_type(a1 / d1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a % b).str(), test_type(a1 % b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a % -b).str(), test_type(a1 % -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a % b).str(), test_type(-a1 % b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a % d).str(), test_type(a1 % d1).str());
       // bitwise ops:
- BOOST_CHECK_EQUAL(mpz_int(a|b).str(), packed_type(a1 | b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a|b).str(), packed_type(-a1 | b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a|-b).str(), packed_type(a1 | -b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a|-b).str(), packed_type(-a1 | -b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a&b).str(), packed_type(a1 & b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a&b).str(), packed_type(-a1 & b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a&-b).str(), packed_type(a1 & -b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a&-b).str(), packed_type(-a1 & -b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a^b).str(), packed_type(a1 ^ b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a^b).str(), packed_type(-a1 ^ b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a^-b).str(), packed_type(a1 ^ -b1).str());
- BOOST_CHECK_EQUAL(mpz_int(-a^-b).str(), packed_type(-a1 ^ -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a|b).str(), test_type(a1 | b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a|b).str(), test_type(-a1 | b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a|-b).str(), test_type(a1 | -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a|-b).str(), test_type(-a1 | -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a&b).str(), test_type(a1 & b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a&b).str(), test_type(-a1 & b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a&-b).str(), test_type(a1 & -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a&-b).str(), test_type(-a1 & -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a^b).str(), test_type(a1 ^ b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a^b).str(), test_type(-a1 ^ b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a^-b).str(), test_type(a1 ^ -b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a^-b).str(), test_type(-a1 ^ -b1).str());
       // Now check operations involving integers:
- BOOST_CHECK_EQUAL(mpz_int(a + si).str(), packed_type(a1 + si).str());
- BOOST_CHECK_EQUAL(mpz_int(a + -si).str(), packed_type(a1 + -si).str());
- BOOST_CHECK_EQUAL(mpz_int(-a + si).str(), packed_type(-a1 + si).str());
- BOOST_CHECK_EQUAL(mpz_int(si + a).str(), packed_type(si + a1).str());
- BOOST_CHECK_EQUAL(mpz_int(a - si).str(), packed_type(a1 - si).str());
- BOOST_CHECK_EQUAL(mpz_int(a - -si).str(), packed_type(a1 - -si).str());
- BOOST_CHECK_EQUAL(mpz_int(-a - si).str(), packed_type(-a1 - si).str());
- BOOST_CHECK_EQUAL(mpz_int(si - a).str(), packed_type(si - a1).str());
- BOOST_CHECK_EQUAL(mpz_int(b * si).str(), packed_type(b1 * si).str());
- BOOST_CHECK_EQUAL(mpz_int(b * -si).str(), packed_type(b1 * -si).str());
- BOOST_CHECK_EQUAL(mpz_int(-b * si).str(), packed_type(-b1 * si).str());
- BOOST_CHECK_EQUAL(mpz_int(si * b).str(), packed_type(si * b1).str());
- BOOST_CHECK_EQUAL(mpz_int(a / si).str(), packed_type(a1 / si).str());
- BOOST_CHECK_EQUAL(mpz_int(a / -si).str(), packed_type(a1 / -si).str());
- BOOST_CHECK_EQUAL(mpz_int(-a / si).str(), packed_type(-a1 / si).str());
- BOOST_CHECK_EQUAL(mpz_int(a % si).str(), packed_type(a1 % si).str());
- BOOST_CHECK_EQUAL(mpz_int(a % -si).str(), packed_type(a1 % -si).str());
- BOOST_CHECK_EQUAL(mpz_int(-a % si).str(), packed_type(-a1 % si).str());
- BOOST_CHECK_EQUAL(mpz_int(a|si).str(), packed_type(a1 | si).str());
- BOOST_CHECK_EQUAL(mpz_int(a&si).str(), packed_type(a1 & si).str());
- BOOST_CHECK_EQUAL(mpz_int(a^si).str(), packed_type(a1 ^ si).str());
- BOOST_CHECK_EQUAL(mpz_int(si|a).str(), packed_type(si|a1).str());
- BOOST_CHECK_EQUAL(mpz_int(si&a).str(), packed_type(si&a1).str());
- BOOST_CHECK_EQUAL(mpz_int(si^a).str(), packed_type(si^a1).str());
- BOOST_CHECK_EQUAL(mpz_int(gcd(a, b)).str(), packed_type(gcd(a1, b1)).str());
- BOOST_CHECK_EQUAL(mpz_int(lcm(c, d)).str(), packed_type(lcm(c1, d1)).str());
- BOOST_CHECK_EQUAL(mpz_int(gcd(-a, b)).str(), packed_type(gcd(-a1, b1)).str());
- BOOST_CHECK_EQUAL(mpz_int(lcm(-c, d)).str(), packed_type(lcm(-c1, d1)).str());
- BOOST_CHECK_EQUAL(mpz_int(gcd(-a, -b)).str(), packed_type(gcd(-a1, -b1)).str());
- BOOST_CHECK_EQUAL(mpz_int(lcm(-c, -d)).str(), packed_type(lcm(-c1, -d1)).str());
- BOOST_CHECK_EQUAL(mpz_int(gcd(a, -b)).str(), packed_type(gcd(a1, -b1)).str());
- BOOST_CHECK_EQUAL(mpz_int(lcm(c, -d)).str(), packed_type(lcm(c1, -d1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(a + si).str(), test_type(a1 + si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a + -si).str(), test_type(a1 + -si).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a + si).str(), test_type(-a1 + si).str());
+ BOOST_CHECK_EQUAL(mpz_int(si + a).str(), test_type(si + a1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a - si).str(), test_type(a1 - si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a - -si).str(), test_type(a1 - -si).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a - si).str(), test_type(-a1 - si).str());
+ BOOST_CHECK_EQUAL(mpz_int(si - a).str(), test_type(si - a1).str());
+ BOOST_CHECK_EQUAL(mpz_int(b * si).str(), test_type(b1 * si).str());
+ BOOST_CHECK_EQUAL(mpz_int(b * -si).str(), test_type(b1 * -si).str());
+ BOOST_CHECK_EQUAL(mpz_int(-b * si).str(), test_type(-b1 * si).str());
+ BOOST_CHECK_EQUAL(mpz_int(si * b).str(), test_type(si * b1).str());
+ BOOST_CHECK_EQUAL(mpz_int(a / si).str(), test_type(a1 / si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a / -si).str(), test_type(a1 / -si).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a / si).str(), test_type(-a1 / si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a % si).str(), test_type(a1 % si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a % -si).str(), test_type(a1 % -si).str());
+ BOOST_CHECK_EQUAL(mpz_int(-a % si).str(), test_type(-a1 % si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a|si).str(), test_type(a1 | si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a&si).str(), test_type(a1 & si).str());
+ BOOST_CHECK_EQUAL(mpz_int(a^si).str(), test_type(a1 ^ si).str());
+ BOOST_CHECK_EQUAL(mpz_int(si|a).str(), test_type(si|a1).str());
+ BOOST_CHECK_EQUAL(mpz_int(si&a).str(), test_type(si&a1).str());
+ BOOST_CHECK_EQUAL(mpz_int(si^a).str(), test_type(si^a1).str());
+ BOOST_CHECK_EQUAL(mpz_int(gcd(a, b)).str(), test_type(gcd(a1, b1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(lcm(c, d)).str(), test_type(lcm(c1, d1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(gcd(-a, b)).str(), test_type(gcd(-a1, b1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(lcm(-c, d)).str(), test_type(lcm(-c1, d1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(gcd(-a, -b)).str(), test_type(gcd(-a1, -b1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(lcm(-c, -d)).str(), test_type(lcm(-c1, -d1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(gcd(a, -b)).str(), test_type(gcd(a1, -b1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(lcm(c, -d)).str(), test_type(lcm(c1, -d1)).str());
       if(last_error_count != boost::detail::test_errors())
       {
          last_error_count = boost::detail::test_errors();
@@ -155,9 +156,9 @@
          std::cout << "a - b = " << a-b << std::endl;
          std::cout << "a1 - b1 = " << a1-b1 << std::endl;
          std::cout << "-a + b = " << mpz_int(-a)+b << std::endl;
- std::cout << "-a1 + b1 = " << packed_type(-a1)+b1 << std::endl;
+ std::cout << "-a1 + b1 = " << test_type(-a1)+b1 << std::endl;
          std::cout << "-a - b = " << mpz_int(-a)-b << std::endl;
- std::cout << "-a1 - b1 = " << packed_type(-a1)-b1 << std::endl;
+ std::cout << "-a1 - b1 = " << test_type(-a1)-b1 << std::endl;
          std::cout << "c*d = " << c*d << std::endl;
          std::cout << "c1*d1 = " << c1*d1 << std::endl;
          std::cout << "b*c = " << b*c << std::endl;
@@ -172,6 +173,13 @@
          std::cout << "a1%d1 = " << a1%d1 << std::endl;
       }
    }
+}
+
+int main()
+{
+ using namespace boost::multiprecision;
+ test<cpp_int>();
+ test<mp_number<cpp_int_backend<1024, true, void> > >();
    return boost::report_errors();
 }
 

Modified: sandbox/big_number/libs/multiprecision/test/test_numeric_limits.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_numeric_limits.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_numeric_limits.cpp 2012-03-08 05:34:37 EST (Thu, 08 Mar 2012)
@@ -134,8 +134,17 @@
    std::cout << "numeric_limits values for type " << typeid(Number).name() << std::endl;
 
    PRINT(is_specialized);
- PRINT(min());
+ if(std::numeric_limits<Number>::is_integer)
+ {
+ std::cout << std::hex << std::showbase;
+ }
+ PRINT(max());
+ if(std::numeric_limits<Number>::is_integer)
+ {
+ std::cout << std::dec;
+ }
    PRINT(max());
+ PRINT(min());
 #ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST
    PRINT(lowest());
 #endif
@@ -225,6 +234,8 @@
 #endif
 #ifdef TEST_CPP_INT
    test<boost::multiprecision::cpp_int>();
+ test<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<256, true, void> > >();
+ test<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<256, false, void> > >();
 #endif
    return boost::report_errors();
 }


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