$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r76234 - in sandbox/big_number: boost/multiprecision libs/multiprecision/test
From: john_at_[hidden]
Date: 2011-12-30 13:21:09
Author: johnmaddock
Date: 2011-12-30 13:21:08 EST (Fri, 30 Dec 2011)
New Revision: 76234
URL: http://svn.boost.org/trac/boost/changeset/76234
Log:
Another Boost.Rational fix.
Add tentative version of a fixed width, bit-packed 2's complement integer type.
Added:
   sandbox/big_number/boost/multiprecision/packed_cpp_int.hpp   (contents, props changed)
Text files modified: 
   sandbox/big_number/boost/multiprecision/mp_number.hpp           |    12 ++                                      
   sandbox/big_number/libs/multiprecision/test/Jamfile.v2          |    28 ++++                                    
   sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp |   240 +++++++++++++++++++++++++---------------
   sandbox/big_number/libs/multiprecision/test/test_int_io.cpp     |    36 +++++                                   
   4 files changed, 221 insertions(+), 95 deletions(-)
Modified: sandbox/big_number/boost/multiprecision/mp_number.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/mp_number.hpp	(original)
+++ sandbox/big_number/boost/multiprecision/mp_number.hpp	2011-12-30 13:21:08 EST (Fri, 30 Dec 2011)
@@ -1635,6 +1635,18 @@
    return a != multiprecision::mp_number<T>(b);
 }
 
+template <class T>
+inline multiprecision::mp_number<T> numerator(const rational<multiprecision::mp_number<T> >& a)
+{
+   return a.numerator();
+}
+
+template <class T>
+inline multiprecision::mp_number<T> denominator(const rational<multiprecision::mp_number<T> >& a)
+{
+   return a.denominator();
+}
+
 } // namespaces
 
 #endif
Added: sandbox/big_number/boost/multiprecision/packed_cpp_int.hpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/boost/multiprecision/packed_cpp_int.hpp	2011-12-30 13:21:08 EST (Fri, 30 Dec 2011)
@@ -0,0 +1,888 @@
+///////////////////////////////////////////////////////////////
+//  Copyright 2011 John Maddock. 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_
+
+#ifndef BOOST_MATH_RATIONAL_ADAPTER_HPP
+#define BOOST_MATH_RATIONAL_ADAPTER_HPP
+
+#include <iostream>
+#include <iomanip>
+#include <boost/cstdint.hpp>
+#include <boost/multiprecision/mp_number.hpp>
+#include <boost/array.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+
+namespace boost{
+namespace multiprecision{
+
+template <unsigned Bits, bool Signed>
+struct packed_cpp_int
+{
+   typedef mpl::list<boost::int32_t, boost::intmax_t>      signed_types;
+   typedef mpl::list<boost::uint32_t, boost::uintmax_t>    unsigned_types;
+   typedef mpl::list<long double>                          float_types;
+
+   typedef boost::uint32_t   limb_type;
+   BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
+   BOOST_STATIC_CONSTANT(unsigned, limb_count = Bits / limb_bits + (Bits % limb_bits ? 1 : 0));
+   BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
+   BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = (Bits % limb_bits ? (1 << (Bits % limb_bits)) - 1 : max_limb_value));
+   BOOST_STATIC_CONSTANT(limb_type, upper_limb_not_mask = ~upper_limb_mask);
+   BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1 << ((Bits % limb_bits ? Bits % limb_bits : limb_bits) - 1));
+   typedef boost::array<limb_type, limb_count> data_type;
+
+   packed_cpp_int(){}
+   packed_cpp_int(const packed_cpp_int& o)
+   {
+      m_value = o.m_value;
+   }
+#ifndef BOOST_NO_RVALUE_REFERENCES
+   packed_cpp_int(packed_cpp_int&& o) : m_value(o.m_value) {}
+#endif
+   packed_cpp_int& operator = (const packed_cpp_int& o)
+   {
+      m_value = o.m_value;
+      return *this;
+   }
+   packed_cpp_int& operator = (boost::uint32_t i)
+   {
+      m_value[limb_count - 1] = i;
+      for(int j = limb_count - 2; j >= 0; --j)
+         m_value[j] = 0;
+      m_value[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+      return *this;
+   }
+   packed_cpp_int& operator = (boost::int32_t i)
+   {
+      m_value[limb_count - 1] = i;
+      // sign extend:
+      for(int j = limb_count - 2; j >= 0; --j)
+         m_value[j] = i < 0 ? max_limb_value : 0;
+      m_value[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+      return *this;
+   }
+   packed_cpp_int& operator = (boost::uintmax_t i)
+   {
+      BOOST_STATIC_ASSERT(sizeof(i) % sizeof(limb_type) == 0);
+      boost::uintmax_t mask = max_limb_value;
+      unsigned shift = 0;
+      for(int j = limb_count - 1; j >= static_cast<int>(limb_count) - static_cast<int>(sizeof(boost::intmax_t) / sizeof(limb_type)); --j)
+      {
+         m_value[j] = static_cast<limb_type>((i & mask) >> shift);
+         mask <<= limb_bits;
+         shift += limb_bits;
+      }
+      for(int j = static_cast<int>(limb_count) - static_cast<int>(sizeof(boost::intmax_t) / sizeof(limb_type)) - 1; j >= 0; --j)
+         m_value[j] = 0;
+      m_value[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+      return *this;
+   }
+   packed_cpp_int& operator = (boost::intmax_t i)
+   {
+      BOOST_STATIC_ASSERT(sizeof(i) % sizeof(limb_type) == 0);
+      boost::uintmax_t mask = max_limb_value;
+      unsigned shift = 0;
+      for(int j = limb_count - 1; j >= static_cast<int>(limb_count) - static_cast<int>(sizeof(boost::intmax_t) / sizeof(limb_type)); --j)
+      {
+         m_value[j] = static_cast<limb_type>((i & mask) >> shift);
+         mask <<= limb_bits;
+         shift += limb_bits;
+      }
+      for(int j = static_cast<int>(limb_count) - static_cast<int>(sizeof(boost::intmax_t) / sizeof(limb_type)) - 1; j >= 0; --j)
+         m_value[j] = i < 0 ? max_limb_value : 0;
+      m_value[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+      return *this;
+   }
+   packed_cpp_int& operator = (long double a)
+   {
+      BOOST_STATIC_ASSERT(Bits >= std::numeric_limits<long double>::digits);
+      using std::frexp;
+      using std::ldexp;
+      using std::floor;
+
+      if (a == 0) {
+         return *this = static_cast<boost::uint32_t>(0u);
+      }
+
+      if (a == 1) {
+         return *this = static_cast<boost::uint32_t>(1u);
+      }
+
+      BOOST_ASSERT(!(boost::math::isinf)(a));
+      BOOST_ASSERT(!(boost::math::isnan)(a));
+
+      int e;
+      long double f, term;
+      *this = static_cast<boost::uint32_t>(0u);
+
+      f = frexp(a, &e);
+
+      static const boost::uint32_t shift = std::numeric_limits<boost::uint32_t>::digits;
+
+      while(f)
+      {
+         // extract int sized bits from f:
+         f = ldexp(f, shift);
+         term = floor(f);
+         e -= shift;
+         left_shift(*this, shift);
+         if(term > 0)
+            add(*this, static_cast<boost::uint32_t>(term));
+         else
+            subtract(*this, static_cast<boost::uint32_t>(-term));
+         f -= term;
+      }
+      if(e > 0)
+         left_shift(*this, e);
+      else if(e < 0)
+         right_shift(*this, -e);
+      data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+      return *this;
+   }
+   packed_cpp_int& operator = (const char* s)
+   {
+      std::size_t n = s ? std::strlen(s) : 0;
+      *this = static_cast<boost::uint32_t>(0u);
+      unsigned radix = 10;
+      bool isneg = false;
+      if(n && (*s == '-'))
+      {
+         --n;
+         ++s;
+         isneg = true;
+      }
+      if(n && (*s == '0'))
+      {
+         if((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
+         {
+            radix = 16;
+            s +=2;
+            n -= 2;
+         }
+         else
+         {
+            radix = 8;
+            n -= 1;
+         }
+      }
+      if(n)
+      {
+         if(radix == 8 || radix == 16)
+         {
+            unsigned shift = radix == 8 ? 3 : 4;
+            boost::uint32_t val = max_limb_value;
+            while(*s)
+            {
+               left_shift(*this, shift);
+               if(*s >= '0' && *s <= '9')
+                  val = *s - '0';
+               else if(*s >= 'a' && *s <= 'f')
+                  val = 10 + *s - 'a';
+               else if(*s >= 'A' && *s <= 'F')
+                  val = 10 + *s - 'A';
+               else
+                  val = max_limb_value;
+               if(val > radix)
+               {
+                  m_value[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+                  return *this; // TODO raise an exception here?
+               }
+               m_value[limb_count - 1] |= val;
+               ++s;
+            }
+         }
+         else
+         {
+            // Base 10:
+            while(*s)
+            {
+               // TODO: this implementation is brain dead, Fix Me!
+               multiply(*this, static_cast<boost::uint32_t>(10));
+               boost::uint32_t val;
+               if(*s >= '0' && *s <= '9')
+                  val = *s - '0';
+               else
+                  return *this; // TODO raise an exception here?
+               add(*this, val);
+               ++s;
+            }
+         }
+      }
+      m_value[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+      if(isneg)
+         negate();
+      return *this;
+   }
+   void swap(packed_cpp_int& o)
+   {
+      std::swap(m_value, o.m_value);
+   }
+   std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
+   {
+      int base = 10;
+      if((f & std::ios_base::oct) == std::ios_base::oct)
+         base = 8;
+      else if((f & std::ios_base::hex) == std::ios_base::hex)
+         base = 16;
+      std::string result;
+
+      if(base == 8 || base == 16)
+      {
+         boost::uint32_t shift = base == 8 ? 3 : 4;
+         boost::uint32_t mask = static_cast<boost::uint32_t>((1u << shift) - 1);
+         packed_cpp_int t(*this);
+         for(unsigned i = 0; i < Bits / shift; ++i)
+         {
+            char c = '0' + (t.data()[limb_count-1] & mask);
+            if(c > '9')
+               c += 'A' - '9' - 1;
+            result.insert(0, 1, c);
+            right_shift(t, shift);
+         }
+         if(Bits % shift)
+         {
+            mask = static_cast<boost::uint32_t>((1u << (Bits % shift)) - 1);
+            char c = '0' + (t.data()[limb_count-1] & mask);
+            if(c > '9')
+               c += 'A' - '9';
+            result.insert(0, 1, c);
+         }
+         //
+         // Get rid of leading zeros:
+         //
+         std::string::size_type n = result.find_first_not_of('0');
+         if(!result.empty() && (n == std::string::npos))
+            n = result.size() - 1;
+         result.erase(0, n);
+         if(f & std::ios_base::showbase)
+         {
+            const char* pp = base == 8 ? "0" : "0x";
+            result.insert(0, pp);
+         }
+      }
+      else
+      {
+         packed_cpp_int t(*this);
+         packed_cpp_int ten, r;
+         ten = boost::uint32_t(1000000000);
+         bool neg = false;
+         if(Signed && (t.data()[0] & sign_bit_mask))
+         {
+            t.negate();
+            neg = true;
+         }
+         if(limb_count == 1)
+         {
+            result = boost::lexical_cast<std::string>(t.data()[0]);
+         }
+         else
+         {
+            while(get_sign(t) != 0)
+            {
+               packed_cpp_int t2;
+               divide_unsigned_helper(t2, t, ten, r);
+               t = t2;
+               boost::uint32_t v = r.data()[limb_count - 1];
+               for(unsigned i = 0; i < 9; ++i)
+               {
+                  char c = '0' + v % 10;
+                  v /= 10;
+                  result.insert(0, 1, c);
+               }
+            }
+         }
+         unsigned n = result.find_first_not_of('0');
+         result.erase(0, n);
+         if(result.empty())
+            result = "0";
+         if(neg)
+            result.insert(0, 1, '-');
+         else if(f & std::ios_base::showpos)
+            result.insert(0, 1, '+');
+      }
+      return result;
+   }
+   void negate()
+   {
+      using default_ops::increment;
+      // complement and add 1:
+      complement(*this, *this);
+      increment(*this);
+   }
+   int compare(const packed_cpp_int& o)const
+   {
+      int result = 0;
+      if(Signed && ((m_value[0] & sign_bit_mask) != (o.data()[0] & sign_bit_mask)))
+      {
+         return m_value[0] & sign_bit_mask ? -1 : 1;
+      }
+      for(data_type::size_type i = 0; i < limb_count; ++i)
+      {
+         if(m_value[i] != o.data()[i])
+         {
+            result = (m_value[i] < o.data()[i]) ? -1 : 1;
+            break;
+         }
+      }
+      return Signed && (m_value[0] & sign_bit_mask) ? -result : result ;
+   }
+   template <class Arithmatic>
+   typename enable_if<is_arithmetic<Arithmatic>, int>::type compare(Arithmatic i)const
+   {
+      // braindead version:
+      packed_cpp_int<Bits, Signed> t;
+      t = i;
+      return compare(t);
+   }
+   data_type& data() { return m_value; }
+   const data_type& data()const { return m_value; }
+private:
+   data_type m_value;
+};
+
+template <unsigned Bits, bool Signed>
+inline void add(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& o)
+{
+   // Addition using modular arithmatic.
+   // Nothing fancy, just let uintmax_t take the strain:
+   boost::uintmax_t carry = 0;
+   for(int i = packed_cpp_int<Bits, Signed>::limb_count - 1; i >= 0; --i)
+   {
+      boost::uintmax_t v = static_cast<boost::uintmax_t>(result.data()[i]) + static_cast<boost::uintmax_t>(o.data()[i]) + carry;
+      result.data()[i] = static_cast<packed_cpp_int<Bits, Signed>::limb_type>(v);
+      carry = v > packed_cpp_int<Bits, Signed>::max_limb_value ? 1 : 0;
+   }
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+template <unsigned Bits, bool Signed>
+inline void add(packed_cpp_int<Bits, Signed>& result, const boost::uint32_t& o)
+{
+   // Addition using modular arithmatic.
+   // Nothing fancy, just let uintmax_t take the strain:
+   boost::uintmax_t carry = o;
+   for(int i = packed_cpp_int<Bits, Signed>::limb_count - 1; carry && i >= 0; --i)
+   {
+      boost::uintmax_t v = static_cast<boost::uintmax_t>(result.data()[i]) + carry;
+      result.data()[i] = static_cast<packed_cpp_int<Bits, Signed>::limb_type>(v);
+      carry = v > packed_cpp_int<Bits, Signed>::max_limb_value ? 1 : 0;
+   }
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+template <unsigned Bits, bool Signed>
+inline void add(packed_cpp_int<Bits, Signed>& result, const boost::int32_t& o)
+{
+   if(o < 0)
+      subtract(result, static_cast<boost::uint32_t>(-o));
+   else if(o > 0)
+      add(result, static_cast<boost::uint32_t>(o));
+}
+template <unsigned Bits, bool Signed>
+inline void subtract(packed_cpp_int<Bits, Signed>& result, const boost::uint32_t& o)
+{
+   if(o)
+   {
+      packed_cpp_int<Bits, Signed> t;
+      t.data()[packed_cpp_int<Bits, Signed>::limb_count - 1] = ~o + 1;
+      for(int i = packed_cpp_int<Bits, Signed>::limb_count - 2; i >= 0; --i)
+      {
+         t.data()[i] = packed_cpp_int<Bits, Signed>::max_limb_value;
+      }
+      add(result, t);
+   }
+}
+template <unsigned Bits, bool Signed>
+inline void subtract(packed_cpp_int<Bits, Signed>& result, const boost::int32_t& o)
+{
+   if(o)
+   {
+      if(o < 0)
+         add(result, static_cast<boost::uint32_t>(-o));
+      else
+         subtract(result, static_cast<boost::uint32_t>(o));
+   }
+}
+template <unsigned Bits, bool Signed>
+inline void increment(packed_cpp_int<Bits, Signed>& result)
+{
+   static const boost::uint32_t one = 1;
+   add(result, one);
+}
+template <unsigned Bits, bool Signed>
+inline void decrement(packed_cpp_int<Bits, Signed>& result)
+{
+   static const boost::uint32_t one = 1;
+   subtract(result, one);
+}
+template <unsigned Bits, bool Signed>
+inline void subtract(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& o)
+{
+   // Negate and add:
+   packed_cpp_int<Bits, Signed> t(o);
+   t.negate();
+   add(result, t);
+}
+template <unsigned Bits, bool Signed>
+inline void multiply(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& a, const packed_cpp_int<Bits, Signed>& 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:
+   if(&result == &a)
+   {
+      packed_cpp_int<Bits, Signed> t(a);
+      multiply(result, t, b);
+      return;
+   }
+   if(&result == &b)
+   {
+      packed_cpp_int<Bits, Signed> t(b);
+      multiply(result, a, t);
+      return;
+   }
+   boost::uintmax_t carry = 0;
+   for(unsigned i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+      result.data()[i] = 0;
+   for(int i = packed_cpp_int<Bits, Signed>::limb_count - 1; i >= 0; --i)
+   {
+      for(int j = packed_cpp_int<Bits, Signed>::limb_count - 1; j >= static_cast<int>(packed_cpp_int<Bits, Signed>::limb_count) - i - 1; --j)
+      {
+         boost::uintmax_t v = static_cast<boost::uintmax_t>(a.data()[i]) * static_cast<boost::uintmax_t>(b.data()[j]) + carry;
+         v += result.data()[i + j + 1 - packed_cpp_int<Bits, Signed>::limb_count];
+         result.data()[i + j + 1 - packed_cpp_int<Bits, Signed>::limb_count] = static_cast<packed_cpp_int<Bits, Signed>::limb_type>(v);
+         carry = v >> sizeof(packed_cpp_int<Bits, Signed>::limb_type) * CHAR_BIT;
+      }
+      carry = 0;
+   }
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+template <unsigned Bits, bool Signed>
+inline void multiply(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& a)
+{
+   // There is no in-place multiply:
+   packed_cpp_int<Bits, Signed> b(result);
+   multiply(result, b, a);
+}
+template <unsigned Bits, bool Signed>
+inline void multiply(packed_cpp_int<Bits, Signed>& result, const boost::uint32_t& a)
+{
+   boost::uintmax_t carry = 0;
+   for(int i = packed_cpp_int<Bits, Signed>::limb_count - 1; i >= 0; --i)
+   {
+      boost::uintmax_t v = static_cast<boost::uintmax_t>(result.data()[i]) * static_cast<boost::uintmax_t>(a) + carry;
+      result.data()[i] = static_cast<packed_cpp_int<Bits, Signed>::limb_type>(v);
+      carry = v >> sizeof(packed_cpp_int<Bits, Signed>::limb_type) * CHAR_BIT;
+   }
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+template <unsigned Bits, bool Signed>
+inline void multiply(packed_cpp_int<Bits, Signed>& result, const boost::int32_t& a)
+{
+   if(a > 0)
+      multiply(result, static_cast<boost::uint32_t>(a));
+   else
+   {
+      multiply(result, static_cast<boost::uint32_t>(-a));
+      result.negate();
+   }
+}
+
+template <unsigned Bits, bool Signed>
+boost::uint32_t bitcount(const packed_cpp_int<Bits, Signed>& a)
+{
+   // returns the location of the MSB in a:
+   boost::uint32_t i = 0;
+   for(; (i < packed_cpp_int<Bits, Signed>::limb_count) && (a.data()[i] == 0); ++i){}
+   boost::uint32_t count = (packed_cpp_int<Bits, Signed>::limb_count - i) * packed_cpp_int<Bits, Signed>::limb_bits;
+   if(!count)
+      return count; // no bits are set, value is zero
+   boost::uint32_t mask = static_cast<boost::uint32_t>(1u) << (packed_cpp_int<Bits, Signed>::limb_bits - 1);
+   while((a.data()[i] & mask) == 0)
+   {
+      --count;
+      mask >>= 1;
+   }
+   return count;
+}
+
+template <unsigned Bits, bool Signed>
+void divide_unsigned_helper(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& x, const packed_cpp_int<Bits, Signed>& y, packed_cpp_int<Bits, Signed>& r)
+{
+   if((&result == &x) || (&r == &x))
+   {
+      packed_cpp_int<Bits, Signed> t(x);
+      divide_unsigned_helper(result, t, y, r);
+      return;
+   }
+   if((&result == &y) || (&r == &y))
+   {
+      packed_cpp_int<Bits, Signed> t(y);
+      divide_unsigned_helper(result, x, t, r);
+      return;
+   }
+
+
+   using default_ops::subtract;
+
+
+   if (is_zero(y))
+   {
+      volatile int i = 0;
+      i /= i;
+      return;
+   }
+
+   if (is_zero(x))
+   {
+      r = y;
+      result = x;
+      return;
+   }
+
+   if(&result == &r)
+   {
+      packed_cpp_int<Bits, Signed> rem;
+      divide_unsigned_helper(result, x, y, rem);
+      r = rem;
+      return;
+   }
+
+   r = x;
+   result = static_cast<boost::uint32_t>(0u);
+   if(x.compare(y) < 0)
+   {
+      return; // We already have the answer: zero.
+   }
+
+   boost::uint32_t n = bitcount(x) - bitcount(y);
+
+   if(n == 0)
+   {
+      // result is exactly 1:
+      result = static_cast<boost::uint32_t>(1u);
+      subtract(r, y);
+      return;
+   }
+
+   // Together mask_index and mask give us the bit we may be about to set in the result:
+   boost::uint32_t mask_index = packed_cpp_int<Bits, Signed>::limb_count - 1 - n / packed_cpp_int<Bits, Signed>::limb_bits;
+   boost::uint32_t mask = static_cast<boost::uint32_t>(1u) << n % packed_cpp_int<Bits, Signed>::limb_bits;
+   packed_cpp_int<Bits, Signed> t(y);
+   left_shift(t, n);
+   while(mask_index < packed_cpp_int<Bits, Signed>::limb_count)
+   {
+      int comp = r.compare(t);
+      if(comp >= 0)
+      {
+         result.data()[mask_index] |= mask;
+         subtract(r, t);
+         if(comp == 0)
+            break; // no remainder left - we have an exact result!
+      }
+      right_shift(t, 1u);
+      if(0 == (mask >>= 1))
+      {
+         ++mask_index;
+         mask = static_cast<boost::uint32_t>(1u) << (packed_cpp_int<Bits, Signed>::limb_bits - 1);
+      }
+   }
+   BOOST_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed
+}
+
+template <unsigned Bits, bool Signed>
+inline void divide(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& a, const packed_cpp_int<Bits, Signed>& b)
+{
+   packed_cpp_int<Bits, Signed> r;
+   if(Signed && (a.data()[0] & packed_cpp_int<Bits, Signed>::sign_bit_mask))
+   {
+      if(Signed && (b.data()[0] & packed_cpp_int<Bits, Signed>::sign_bit_mask))
+      {
+         packed_cpp_int<Bits, Signed> t1(a), t2(b);
+         t1.negate();
+         t2.negate();
+         divide_unsigned_helper(result, t1, t2, r);
+      }
+      else
+      {
+         packed_cpp_int<Bits, Signed> t(a);
+         t.negate();
+         divide_unsigned_helper(result, t, b, r);
+         result.negate();
+      }
+   }
+   else if(Signed && (b.data()[0] & packed_cpp_int<Bits, Signed>::sign_bit_mask))
+   {
+      packed_cpp_int<Bits, Signed> t(b);
+      t.negate();
+      divide_unsigned_helper(result, a, t, r);
+      result.negate();
+   }
+   else
+   {
+      divide_unsigned_helper(result, a, b, r);
+   }
+}
+template <unsigned Bits, bool Signed>
+inline void divide(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& b)
+{
+   // There is no in place divide:
+   packed_cpp_int<Bits, Signed> a(result);
+   divide(result, a, b);
+}
+template <unsigned Bits, bool Signed>
+inline void modulus(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& a, const packed_cpp_int<Bits, Signed>& b)
+{
+   packed_cpp_int<Bits, Signed> r;
+   if(Signed && (a.data()[0] & packed_cpp_int<Bits, Signed>::sign_bit_mask))
+   {
+      if(Signed && (b.data()[0] & packed_cpp_int<Bits, Signed>::sign_bit_mask))
+      {
+         packed_cpp_int<Bits, Signed> t1(a), t2(b);
+         t1.negate();
+         t2.negate();
+         divide_unsigned_helper(r, t1, t2, result);
+         result.negate();
+      }
+      else
+      {
+         packed_cpp_int<Bits, Signed> t(a);
+         t.negate();
+         divide_unsigned_helper(r, t, b, result);
+         result.negate();
+      }
+   }
+   else if(Signed && (b.data()[0] & packed_cpp_int<Bits, Signed>::sign_bit_mask))
+   {
+      packed_cpp_int<Bits, Signed> t(b);
+      t.negate();
+      divide_unsigned_helper(r, a, t, result);
+   }
+   else
+   {
+      divide_unsigned_helper(r, a, b, result);
+   }
+}
+template <unsigned Bits, bool Signed>
+inline void modulus(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& b)
+{
+   // There is no in place divide:
+   packed_cpp_int<Bits, Signed> a(result);
+   modulus(result, a, b);
+}
+
+template <unsigned Bits, bool Signed>
+inline void bitwise_and(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& o)
+{
+   for(packed_cpp_int<Bits, Signed>::data_type::size_type i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+      result.data()[i] &= o.data()[i];
+}
+template <unsigned Bits, bool Signed>
+inline void bitwise_or(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& o)
+{
+   for(packed_cpp_int<Bits, Signed>::data_type::size_type i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+      result.data()[i] |= o.data()[i];
+}
+template <unsigned Bits, bool Signed>
+inline void bitwise_xor(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& o)
+{
+   for(packed_cpp_int<Bits, Signed>::data_type::size_type i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+      result.data()[i] ^= o.data()[i];
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+template <unsigned Bits, bool Signed>
+inline void complement(packed_cpp_int<Bits, Signed>& result, const packed_cpp_int<Bits, Signed>& o)
+{
+   for(packed_cpp_int<Bits, Signed>::data_type::size_type i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+      result.data()[i] = ~o.data()[i];
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+template <unsigned Bits, bool Signed>
+inline void left_shift(packed_cpp_int<Bits, Signed>& result, boost::uintmax_t s)
+{
+   if(s >= Bits)
+   {
+      result = static_cast<boost::uint32_t>(0);
+      return;
+   }
+   boost::uint32_t offset = static_cast<boost::uint32_t>(s / packed_cpp_int<Bits, Signed>::limb_bits);
+   boost::uint32_t shift  = static_cast<boost::uint32_t>(s % packed_cpp_int<Bits, Signed>::limb_bits);
+   unsigned i = 0;
+   if(shift)
+   {
+      // This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
+      for(; i + offset + 1 < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+      {
+         result.data()[i] = result.data()[i+offset] << shift;
+         result.data()[i] |= result.data()[i+offset+1] >> (packed_cpp_int<Bits, Signed>::limb_bits - shift);
+      }
+      result.data()[i] = result.data()[i+offset] << shift;
+      ++i;
+      for(; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+         result.data()[i] = 0;
+   }
+   else
+   {
+      for(; i + offset < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+         result.data()[i] = result.data()[i+offset];
+      for(; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+         result.data()[i] = 0;
+   }
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+template <unsigned Bits, bool Signed>
+inline void right_shift(packed_cpp_int<Bits, Signed>& result, boost::uintmax_t s)
+{
+   boost::uint32_t fill = (Signed && (result.data()[0] & packed_cpp_int<Bits, Signed>::sign_bit_mask)) ? packed_cpp_int<Bits, Signed>::max_limb_value : 0u;
+   if(s >= Bits)
+   {
+      for(unsigned i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+         result.data()[i] = fill;
+      return;
+   }
+   boost::uint32_t offset = static_cast<boost::uint32_t>(s / packed_cpp_int<Bits, Signed>::limb_bits);
+   boost::uint32_t shift  = static_cast<boost::uint32_t>(s % packed_cpp_int<Bits, Signed>::limb_bits);
+   int i = packed_cpp_int<Bits, Signed>::limb_count - 1;
+   if(shift)
+   {
+      // This code only works for non-zero shift, otherwise we invoke undefined behaviour!
+      if(fill && (Bits % packed_cpp_int<Bits, Signed>::limb_bits))
+      {
+         // We need to sign extend the leftmost bits, otherwise we may shift zeros into the result:
+         result.data()[0] |= fill << (Bits % packed_cpp_int<Bits, Signed>::limb_bits);
+      }
+      for(; i - offset > 0; --i)
+      {
+         result.data()[i] = result.data()[i-offset] >> shift;
+         result.data()[i] |= result.data()[i-offset-1] << (packed_cpp_int<Bits, Signed>::limb_bits - shift);
+      }
+      result.data()[i] = result.data()[i+offset] >> shift;
+      result.data()[i] |= fill << (packed_cpp_int<Bits, Signed>::limb_bits - shift);
+      --i;
+      for(; i >= 0; --i)
+         result.data()[i] = fill;
+   }
+   else
+   {
+      for(; i - offset > 0; --i)
+         result.data()[i] = result.data()[i - offset];
+      for(; i >= 0; --i)
+         result.data()[i] = fill;
+   }
+   result.data()[0] &= packed_cpp_int<Bits, Signed>::upper_limb_mask;
+}
+
+template <class R, unsigned Bits, bool Signed>
+inline typename enable_if<is_integral<R>, void>::type convert_to(R* result, const packed_cpp_int<Bits, Signed>& backend)
+{
+   unsigned shift = (packed_cpp_int<Bits, Signed>::limb_count - 1) * packed_cpp_int<Bits, Signed>::limb_bits;
+   *result = 0;
+   for(unsigned i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+   {
+      *result += static_cast<R>(backend.data()[i]) << shift;
+      shift -= packed_cpp_int<Bits, Signed>::limb_bits;
+   }
+}
+
+template <class R, unsigned Bits, bool Signed>
+inline typename enable_if<is_floating_point<R>, void>::type convert_to(R* result, const packed_cpp_int<Bits, Signed>& backend)
+{
+   unsigned shift = (packed_cpp_int<Bits, Signed>::limb_count - 1) * packed_cpp_int<Bits, Signed>::limb_bits;
+   *result = 0;
+   for(unsigned i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+   {
+      *result += static_cast<R>(std::ldexp(static_cast<double>(backend.data()[i]), shift));
+      shift -= packed_cpp_int<Bits, Signed>::limb_bits;
+   }
+}
+
+template <unsigned Bits, bool Signed>
+inline bool is_zero(const packed_cpp_int<Bits, Signed>& val)
+{
+   for(typename packed_cpp_int<Bits, Signed>::data_type::size_type i = 0; i < packed_cpp_int<Bits, Signed>::limb_count; ++i)
+   {
+      if(val.data()[i])
+         return false;
+   }
+   return true;
+}
+template <unsigned Bits>
+inline int get_sign(const packed_cpp_int<Bits, false>& val)
+{
+   return is_zero(val) ? 0 : 1;
+}
+template <unsigned Bits>
+inline int get_sign(const packed_cpp_int<Bits, true>& val)
+{
+   return is_zero(val) ? 0 : val.data()[0] & packed_cpp_int<Bits, true>::sign_bit_mask ? -1 : 1;
+}
+
+template <unsigned Bits, bool Signed>
+struct number_category<packed_cpp_int<Bits, Signed> > : public mpl::int_<number_kind_integer>{};
+
+typedef mp_number<packed_cpp_int<64, false> > mp_uint64_t;
+typedef mp_number<packed_cpp_int<128, false> > mp_uint128_t;
+typedef mp_number<packed_cpp_int<256, false> > mp_uint256_t;
+typedef mp_number<packed_cpp_int<512, false> > mp_uint512_t;
+
+typedef mp_number<packed_cpp_int<64, true> > mp_int64_t;
+typedef mp_number<packed_cpp_int<128, true> > mp_int128_t;
+typedef mp_number<packed_cpp_int<256, true> > mp_int256_t;
+typedef mp_number<packed_cpp_int<512, true> > mp_int512_t;
+
+}} // namespaces
+
+
+namespace std{
+
+template <unsigned Bits, bool Signed>
+class numeric_limits<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > >
+{
+   typedef boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<Bits, Signed> > number_type;
+public:
+   BOOST_STATIC_CONSTEXPR bool is_specialized = true;
+   //
+   // Largest and smallest numbers are bounded only by available memory, set
+   // to zero:
+   //
+   BOOST_STATIC_CONSTEXPR number_type (min)() BOOST_MP_NOEXCEPT
+   { 
+      return number_type();
+   }
+   BOOST_STATIC_CONSTEXPR number_type (max)() BOOST_MP_NOEXCEPT 
+   { 
+      return number_type();
+   }
+   BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_MP_NOEXCEPT { return (min)(); }
+   BOOST_STATIC_CONSTEXPR int digits = Bits;
+   BOOST_STATIC_CONSTEXPR int digits10 = (digits * 301L) / 1000;
+   BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
+   BOOST_STATIC_CONSTEXPR bool is_signed = Signed;
+   BOOST_STATIC_CONSTEXPR bool is_integer = true;
+   BOOST_STATIC_CONSTEXPR bool is_exact = true;
+   BOOST_STATIC_CONSTEXPR int radix = 2;
+   BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_MP_NOEXCEPT { return number_type(); }
+   BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_MP_NOEXCEPT { return number_type(); }
+   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;
+   BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_MP_NOEXCEPT { return number_type(); }
+   BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_MP_NOEXCEPT { return number_type(); }
+   BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_MP_NOEXCEPT { return number_type(); }
+   BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_MP_NOEXCEPT { return number_type(); }
+   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;
+};
+
+}
+
+#endif
Modified: sandbox/big_number/libs/multiprecision/test/Jamfile.v2
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/Jamfile.v2	(original)
+++ sandbox/big_number/libs/multiprecision/test/Jamfile.v2	2011-12-30 13:21:08 EST (Fri, 30 Dec 2011)
@@ -128,6 +128,20 @@
          [ check-target-builds ../config//has_tommath : : <build>no ]
         : test_arithmetic_tommath_br ;
 
+run test_arithmetic.cpp
+        : # command line
+        : # input files
+        : # requirements
+	      <define>TEST_PACKED_INT1
+        : test_arithmetic_packed_int1 ;
+
+run test_arithmetic.cpp
+        : # command line
+        : # input files
+        : # requirements
+	      <define>TEST_PACKED_INT2
+        : test_arithmetic_packed_int2 ;
+
 run test_numeric_limits.cpp
         : # command line
         : # input files
@@ -567,6 +581,20 @@
          [ check-target-builds ../config//has_gmp : : <build>no ]
         : test_int_io_mpz ;
 
+run test_int_io.cpp
+        : # command line
+        : # input files
+        : # requirements
+	      <define>TEST_PACKED_INT1
+        : test_int_io_packed_int1 ;
+
+run test_int_io.cpp
+        : # command line
+        : # input files
+        : # requirements
+	      <define>TEST_PACKED_INT2
+        : test_int_io_packed_int2 ;
+
 run test_rational_io.cpp $(TOMMATH)
         : # command line
         : # input files
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	2011-12-30 13:21:08 EST (Fri, 30 Dec 2011)
@@ -12,7 +12,8 @@
 
 #if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && \
    !defined(TEST_CPP_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) \
-   && !defined(TEST_TOMMATH) && !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL)
+   && !defined(TEST_TOMMATH) && !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL)\
+   && !defined(TEST_PACKED_INT1) && !defined(TEST_PACKED_INT2)
 #  define TEST_MPF_50
 #  define TEST_MPF
 #  define TEST_BACKEND
@@ -22,6 +23,8 @@
 #  define TEST_CPP_FLOAT
 #  define TEST_MPQ
 #  define TEST_TOMMATH
+#  define TEST_PACKED_INT1
+#  define TEST_PACKED_INT2
 
 #ifdef _MSC_VER
 #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
@@ -49,6 +52,9 @@
 #include <boost/multiprecision/tommath.hpp>
 #include <boost/multiprecision/rational_adapter.hpp>
 #endif
+#if defined(TEST_PACKED_INT1) || defined(TEST_PACKED_INT2)
+#include <boost/multiprecision/packed_cpp_int.hpp>
+#endif
 #if defined(TEST_TOMMATH_BOOST_RATIONAL) || defined(TEST_MPZ_BOOST_RATIONAL)
 #include <boost/rational.hpp>
 
@@ -151,70 +157,79 @@
    BOOST_TEST(a % b == 20 % 7);
    BOOST_TEST(a % 7 == 20 % 7);
    BOOST_TEST(a % 7u == 20 % 7);
-   BOOST_TEST(-a % b == -20 % 7);
-   BOOST_TEST(-a % -b == -20 % -7);
-   BOOST_TEST(a % -b == 20 % -7);
-   BOOST_TEST(-a % 7 == -20 % 7);
-   BOOST_TEST(-a % -7 == -20 % -7);
-   BOOST_TEST(a % -7 == 20 % -7);
-   BOOST_TEST(-a % 7u == -20 % 7);
-   BOOST_TEST(-a % a == 0);
    BOOST_TEST(a % a == 0);
-   BOOST_TEST(-a % c == 0);
    BOOST_TEST(a % c == 0);
-   BOOST_TEST(-a % 5 == 0);
    BOOST_TEST(a % 5 == 0);
-   BOOST_TEST(-a % -5 == 0);
-   BOOST_TEST(a % -5 == 0);
-
-   b = -b;
-   BOOST_TEST(a % b == 20 % -7);
-   a = -a;
-   BOOST_TEST(a % b == -20 % -7);
-   BOOST_TEST(a % -7 == -20 % -7);
-   b = 7;
-   BOOST_TEST(a % b == -20 % 7);
-   BOOST_TEST(a % 7 == -20 % 7);
-   BOOST_TEST(a % 7u == -20 % 7);
-
-   a = 20;
-   a %= b;
-   BOOST_TEST(a == 20 % 7);
-   a = -20;
-   a %= b;
-   BOOST_TEST(a == -20 % 7);
-   a = 20;
-   a %= -b;
-   BOOST_TEST(a == 20 % -7);
-   a = -20;
-   a %= -b;
-   BOOST_TEST(a == -20 % -7);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      BOOST_TEST(-a % c == 0);
+      BOOST_TEST(-a % b == -20 % 7);
+      BOOST_TEST(-a % -b == -20 % -7);
+      BOOST_TEST(a % -b == 20 % -7);
+      BOOST_TEST(-a % 7 == -20 % 7);
+      BOOST_TEST(-a % -7 == -20 % -7);
+      BOOST_TEST(a % -7 == 20 % -7);
+      BOOST_TEST(-a % 7u == -20 % 7);
+      BOOST_TEST(-a % a == 0);
+      BOOST_TEST(-a % 5 == 0);
+      BOOST_TEST(-a % -5 == 0);
+      BOOST_TEST(a % -5 == 0);
+
+      b = -b;
+      BOOST_TEST(a % b == 20 % -7);
+      a = -a;
+      BOOST_TEST(a % b == -20 % -7);
+      BOOST_TEST(a % -7 == -20 % -7);
+      b = 7;
+      BOOST_TEST(a % b == -20 % 7);
+      BOOST_TEST(a % 7 == -20 % 7);
+      BOOST_TEST(a % 7u == -20 % 7);
+
+      a = 20;
+      a %= b;
+      BOOST_TEST(a == 20 % 7);
+      a = -20;
+      a %= b;
+      BOOST_TEST(a == -20 % 7);
+      a = 20;
+      a %= -b;
+      BOOST_TEST(a == 20 % -7);
+      a = -20;
+      a %= -b;
+      BOOST_TEST(a == -20 % -7);
+   }
 
    a = 20;
    a %= 7;
    BOOST_TEST(a == 20 % 7);
-   a = -20;
-   a %= 7;
-   BOOST_TEST(a == -20 % 7);
-   a = 20;
-   a %= -7;
-   BOOST_TEST(a == 20 % -7);
-   a = -20;
-   a %= -7;
-   BOOST_TEST(a == -20 % -7);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      a = -20;
+      a %= 7;
+      BOOST_TEST(a == -20 % 7);
+      a = 20;
+      a %= -7;
+      BOOST_TEST(a == 20 % -7);
+      a = -20;
+      a %= -7;
+      BOOST_TEST(a == -20 % -7);
+   }
 #ifndef BOOST_NO_LONG_LONG
    a = 20;
    a %= 7uLL;
    BOOST_TEST(a == 20 % 7);
-   a = -20;
-   a %= 7uLL;
-   BOOST_TEST(a == -20 % 7);
-   a = 20;
-   a %= -7LL;
-   BOOST_TEST(a == 20 % -7);
-   a = -20;
-   a %= -7LL;
-   BOOST_TEST(a == -20 % -7);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      a = -20;
+      a %= 7uLL;
+      BOOST_TEST(a == -20 % 7);
+      a = 20;
+      a %= -7LL;
+      BOOST_TEST(a == 20 % -7);
+      a = -20;
+      a %= -7LL;
+      BOOST_TEST(a == -20 % -7);
+   }
 #endif
    a = 20;
    BOOST_TEST(++a == 21);
@@ -330,14 +345,17 @@
    //
    // Non-member functions:
    //
-   a = -20;
-   BOOST_TEST(abs(a) == 20);
-   BOOST_TEST(abs(-a) == 20);
-   BOOST_TEST(abs(+a) == 20);
-   a = 20;
-   BOOST_TEST(abs(a) == 20);
-   BOOST_TEST(abs(-a) == 20);
-   BOOST_TEST(abs(+a) == 20);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      a = -20;
+      BOOST_TEST(abs(a) == 20);
+      BOOST_TEST(abs(-a) == 20);
+      BOOST_TEST(abs(+a) == 20);
+      a = 20;
+      BOOST_TEST(abs(a) == 20);
+      BOOST_TEST(abs(-a) == 20);
+      BOOST_TEST(abs(+a) == 20);
+   }
 }
 
 template <class Real, class T>
@@ -410,6 +428,8 @@
 template <class Real, class Num>
 void test_negative_mixed(boost::mpl::true_ const&)
 {
+   if(std::numeric_limits<Real>::is_specialized && !std::numeric_limits<Real>::is_signed)
+      return;
    typedef typename lexical_cast_target_type<Num>::type target_type;
    std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name()  << " and " << typeid(Num).name() << std::endl;
    Num n1 = -static_cast<Num>(1uLL << (std::numeric_limits<Num>::digits - 1));
@@ -649,7 +669,10 @@
    BOOST_TEST(a == 8);
    Real ac(a);
    BOOST_TEST(ac == a);
-   BOOST_TEST(-a == -8);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      BOOST_TEST(-a == -8);
+   }
    ac = a * c;
    BOOST_TEST(ac == 8*500L);
    ac = 8*500L;
@@ -693,9 +716,12 @@
    ac = a;
    ac = a + ac;
    BOOST_TEST(ac == 16);
-   ac = a;
-   ac = ac - b;
-   BOOST_TEST(ac == 8 - 64);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      ac = a;
+      ac = ac - b;
+      BOOST_TEST(ac == 8 - 64);
+   }
    ac = a;
    ac = a - ac;
    BOOST_TEST(ac == 0);
@@ -705,16 +731,22 @@
    ac = a;
    ac += b + a;
    BOOST_TEST(ac == 80);
-   ac = a;
-   ac -= a + b;
-   BOOST_TEST(ac == -64);
-   ac = a;
-   ac -= b - a;
-   BOOST_TEST(ac == 16 - 64);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      ac = a;
+      ac -= a + b;
+      BOOST_TEST(ac == -64);
+      ac = a;
+      ac -= b - a;
+      BOOST_TEST(ac == 16 - 64);
+   }
    ac = +a;
    BOOST_TEST(ac == 8);
-   ac = -a;
-   BOOST_TEST(ac == -8);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      ac = -a;
+      BOOST_TEST(ac == -8);
+   }
    ac = 8;
    ac = a * ac;
    BOOST_TEST(ac == 8*8);
@@ -736,8 +768,11 @@
    ac -= +a;
    BOOST_TEST(ac == 0);
    ac = a;
-   ac -= -a;
-   BOOST_TEST(ac == 16);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      ac -= -a;
+      BOOST_TEST(ac == 16);
+   }
    ac = a;
    ac -= c - b;
    BOOST_TEST(ac == 8 - (500-64));
@@ -768,9 +803,12 @@
    ac = b;
    ac /= +a;
    BOOST_TEST(ac == 8);
-   ac = b;
-   ac /= -a;
-   BOOST_TEST(ac == -8);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      ac = b;
+      ac /= -a;
+      BOOST_TEST(ac == -8);
+   }
    ac = b;
    ac /= b / a;
    BOOST_TEST(ac == 64 / (64/8));
@@ -788,14 +826,17 @@
    BOOST_TEST(ac == 72);
    ac = +a + +b;
    BOOST_TEST(ac == 72);
-   ac = a + -b;
-   BOOST_TEST(ac == 8 - 64);
-   ac = -a + b;
-   BOOST_TEST(ac == -8+64);
-   ac = -a + -b;
-   BOOST_TEST(ac == -72);
-   ac = a + - + -b; // lots of unary operators!!
-   BOOST_TEST(ac == 72);
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      ac = a + -b;
+      BOOST_TEST(ac == 8 - 64);
+      ac = -a + b;
+      BOOST_TEST(ac == -8+64);
+      ac = -a + -b;
+      BOOST_TEST(ac == -72);
+      ac = a + - + -b; // lots of unary operators!!
+      BOOST_TEST(ac == 72);
+   }
    ac = a;
    ac = b / ac;
    BOOST_TEST(ac == b / a);
@@ -855,9 +896,12 @@
    a = 20;
    BOOST_TEST(a.sign() > 0);
    BOOST_TEST(!a.is_zero());
-   a = -20;
-   BOOST_TEST(a.sign() < 0);
-   BOOST_TEST(!a.is_zero());
+   if(std::numeric_limits<Real>::is_signed)
+   {
+      a = -20;
+      BOOST_TEST(a.sign() < 0);
+      BOOST_TEST(!a.is_zero());
+   }
    a = 0;
    BOOST_TEST(a.sign() == 0);
    BOOST_TEST(a.is_zero());
@@ -955,6 +999,22 @@
 #ifdef TEST_MPZ_BOOST_RATIONAL
    test<boost::rational<boost::multiprecision::mpz_int> >();
 #endif
+#ifdef TEST_PACKED_INT1
+   test<boost::multiprecision::mp_uint64_t>();
+   test<boost::multiprecision::mp_uint128_t>();
+   test<boost::multiprecision::mp_uint512_t>();
+   test<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<70, false> > >();
+#endif
+#ifdef TEST_PACKED_INT2
+   //
+   // Can't test 64-bit signed ints - they don't have enough bits
+   // to interoperate with uint64_t without loss:
+   //
+   //test<boost::multiprecision::mp_int64_t>();
+   test<boost::multiprecision::mp_int128_t>();
+   test<boost::multiprecision::mp_int512_t>();
+   test<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<70, true> > >();
+#endif
    return boost::report_errors();
 }
 
Modified: sandbox/big_number/libs/multiprecision/test/test_int_io.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_int_io.cpp	(original)
+++ sandbox/big_number/libs/multiprecision/test/test_int_io.cpp	2011-12-30 13:21:08 EST (Fri, 30 Dec 2011)
@@ -9,9 +9,11 @@
 #  define _SCL_SECURE_NO_WARNINGS
 #endif
 
-#if !defined(TEST_MPZ) && !defined(TEST_TOMMATH)
+#if !defined(TEST_MPZ) && !defined(TEST_TOMMATH) && !defined(TEST_PACKED_INT1) && !defined(TEST_PACKED_INT2)
 #  define TEST_TOMMATH
 #  define TEST_MPZ
+#  define TEST_PACKED_INT1
+#  define TEST_PACKED_INT2
 
 #ifdef _MSC_VER
 #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
@@ -28,6 +30,9 @@
 #if defined(TEST_TOMMATH)
 #include <boost/multiprecision/tommath.hpp>
 #endif
+#if defined(TEST_PACKED_INT1) || defined(TEST_PACKED_INT2)
+#include <boost/multiprecision/packed_cpp_int.hpp>
+#endif
 
 #include <boost/algorithm/string/case_conv.hpp>
 #include <boost/random/mersenne_twister.hpp>
@@ -82,12 +87,16 @@
    {
       T val = generate_random<T>();
       do_round_trip(val);
-      do_round_trip(T(-val));
+      if(std::numeric_limits<T>::is_signed)
+         do_round_trip(T(-val));
    }
 
    BOOST_CHECK_EQUAL(T(1002).str(), "1002");
    BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::showpos), "+1002");
-   BOOST_CHECK_EQUAL(T(-1002).str(), "-1002");
+   if(std::numeric_limits<T>::is_signed)
+   {
+      BOOST_CHECK_EQUAL(T(-1002).str(), "-1002");
+   }
    BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct), "1752");
    BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct|std::ios_base::showbase), "01752");
    BOOST_CHECK_EQUAL(boost::to_lower_copy(T(1002).str(0, std::ios_base::hex)), "3ea");
@@ -95,8 +104,11 @@
    BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec), "1002");
    BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec|std::ios_base::showbase), "1002");
 
-   BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::oct), std::runtime_error);
-   BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::hex), std::runtime_error);
+   if(std::numeric_limits<T>::is_signed && !std::numeric_limits<T>::is_modulo)
+   {
+      BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::oct), std::runtime_error);
+      BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::hex), std::runtime_error);
+   }
 }
 
 int main()
@@ -107,6 +119,20 @@
 #ifdef TEST_TOMMATH
    test_round_trip<boost::multiprecision::mp_int>();
 #endif
+#ifdef TEST_PACKED_INT1
+   test_round_trip<boost::multiprecision::mp_uint64_t>();
+   test_round_trip<boost::multiprecision::mp_uint128_t>();
+   test_round_trip<boost::multiprecision::mp_uint512_t>();
+   test_round_trip<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<20, false> > >();
+   test_round_trip<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<70, false> > >();
+#endif
+#ifdef TEST_PACKED_INT2
+   test_round_trip<boost::multiprecision::mp_int64_t>();
+   test_round_trip<boost::multiprecision::mp_int128_t>();
+   test_round_trip<boost::multiprecision::mp_int512_t>();
+   test_round_trip<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<20, true> > >();
+   test_round_trip<boost::multiprecision::mp_number<boost::multiprecision::packed_cpp_int<70, true> > >();
+#endif
    return boost::report_errors();
 }