$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r49446 - in sandbox/mp_math: . boost boost/mp_math boost/mp_math/mp_int boost/mp_math/mp_int/detail boost/mp_math/mp_int/detail/asm boost/mp_math/mp_int/detail/asm/x86 libs libs/mp_math libs/mp_math/doc libs/mp_math/doc/html libs/mp_math/doc/html/benchmark_imgs libs/mp_math/doc/html/benchmark_imgs/k7 libs/mp_math/doc/html/mp_int_ libs/mp_math/test libs/mp_math/tools libs/mp_math/tools/benchmark
From: baraclese_at_[hidden]
Date: 2008-10-24 14:49:44
Author: baraclese
Date: 2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
New Revision: 49446
URL: http://svn.boost.org/trac/boost/changeset/49446
Log:
Initial commit.
Added:
   sandbox/mp_math/
   sandbox/mp_math/LICENSE_1_0.txt   (contents, props changed)
   sandbox/mp_math/boost/
   sandbox/mp_math/boost.png   (contents, props changed)
   sandbox/mp_math/boost/mp_math/
   sandbox/mp_math/boost/mp_math/mp_int/
   sandbox/mp_math/boost/mp_math/mp_int.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/abs.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/add.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/detail/
   sandbox/mp_math/boost/mp_math/mp_int/detail/asm/
   sandbox/mp_math/boost/mp_math/mp_int/detail/asm/x86/
   sandbox/mp_math/boost/mp_math/mp_int/detail/asm/x86/gnu_386_primitive_ops.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/detail/meta_math.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/detail/prime_tab.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/detail/string_conversion_constants.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/div.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/mod.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/modular_reduction.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/mul.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/numeric_limits.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/operators.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/pow.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/prime.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/random.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/root.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/sub.hpp   (contents, props changed)
   sandbox/mp_math/boost/mp_math/mp_int/traits.hpp   (contents, props changed)
   sandbox/mp_math/libs/
   sandbox/mp_math/libs/mp_math/
   sandbox/mp_math/libs/mp_math/doc/
   sandbox/mp_math/libs/mp_math/doc/bibliography.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/add.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/ctor_dec.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/ctor_hex.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/divide.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/input_vecs.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/modpow.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/modulo.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/multiply.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/square.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/subtract.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/to_dec.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/to_hex.png   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/boostbook.css   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/index.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/bibliography.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/implementation_notes.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/mp_int_reference.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/mp_int_traits_reference.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/performance.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/primality_tests_reference.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/tutorial.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/uniform_mp_int_bits_reference.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/html/mp_int_/uniform_mp_int_reference.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/implementation_notes.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/introduction.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/jamfile.v2   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/mp_int.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/mp_int_reference.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/mp_int_traits_reference.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/performance.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/primality_tests_reference.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/tutorial.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/uniform_mp_int_bits_reference.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/doc/uniform_mp_int_reference.qbk   (contents, props changed)
   sandbox/mp_math/libs/mp_math/index.html   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/
   sandbox/mp_math/libs/mp_math/test/add.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/bitwise_ops.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/bool_conversion.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/cmp.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/compile_all.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/ctors.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/div.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/gcd.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/integral_ops.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/jacobi.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/jamfile.v2   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/mul.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/pow.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/prerequisite.hpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/prime.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/random.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/root.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/serialization.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/shift.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/sqr.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/stream_io.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/string_ops.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/sub.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/to_integral.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/traits.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/
   sandbox/mp_math/libs/mp_math/tools/benchmark/
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.hpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_libtom.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_libtom.hpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_mp_math.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_mp_math.hpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_result.hpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.hpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/tommath.cpp   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/tommath.h   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/tommath_class.h   (contents, props changed)
   sandbox/mp_math/libs/mp_math/tools/benchmark/tommath_superclass.h   (contents, props changed)
   sandbox/mp_math/project-root.jam   (contents, props changed)
Added: sandbox/mp_math/LICENSE_1_0.txt
==============================================================================
--- (empty file)
+++ sandbox/mp_math/LICENSE_1_0.txt	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
Added: sandbox/mp_math/boost.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/boost/mp_math/mp_int.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,11 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_HPP
+#define BOOST_MP_MATH_MP_INT_HPP
+
+#include <boost/mp_math/mp_int/mp_int.hpp>
+
+#endif
Added: sandbox/mp_math/boost/mp_math/mp_int/abs.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/abs.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,12 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+template<class A, class T>
+mp_int<A,T> abs(const mp_int<A,T>& x)
+{
+  mp_int<A,T> tmp(x);
+  tmp.sign_ = 1;
+  return tmp;
+}
Added: sandbox/mp_math/boost/mp_math/mp_int/add.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/add.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,87 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+template<class A, class T>
+void mp_int<A,T>::add_digit(digit_type b)
+{
+  if (is_positive())
+  {
+    grow_capacity(used_ + 1);
+    const digit_type carry =
+      ops_type::add_single_digit(digits_, digits_, used_, b);
+    if (carry)
+      digits_[used_++] = carry;
+  }
+  else
+  {
+    if (digits_[0] >= b) // example: -16 + 5 = -11; or -5 + 5 = 0
+    {
+      digits_[0] -= b;
+      if (is_zero())
+        sign_ = 1;
+    }
+    else
+    {
+      if (used_ == 1) // example: -1 + 5 = 4
+        digits_[0] = b - digits_[0];
+      else            // example -11 + 5 = -6
+      {
+        sign_ = 1;
+        sub_digit(b);
+        sign_ = -1;
+      }
+    }
+  }
+}
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+// does not handle sign
+template<class A, class T>
+void mp_int<A,T>::add_magnitude(const mp_int& rhs)
+{
+  const mp_int* x;
+  const mp_int* y;
+
+  // x will point to the number with the most digits
+  if (used_ > rhs.used_)
+  {
+    x = this;
+    y = &rhs;
+  }
+  else
+  {
+    x = &rhs;
+    y = this;
+  }
+
+  grow_capacity(x->used_ + 1);
+
+  digit_type carry = ops_type::add_digits(digits_,
+                                          x->digits_,
+                                          y->digits_, y->used_);
+
+  size_type n = ops_type::ripple_carry(digits_ + y->used_,
+                                       x->digits_ + y->used_,
+                                       x->used_ - y->used_, carry);
+  n += y->used_;
+
+  if (n < x->used_) // this implies that there is no carry left
+  {
+    if (x != this)
+    {
+      std::memcpy(digits_ + n, x->digits_ + n, sizeof(digit_type) * (x->used_ - n));
+      used_ = x->used_;
+    }
+    return;
+  }
+  else if (carry) // at this point n equals x->used_
+  {
+    digits_[n] = carry;
+    ++n;
+  }
+
+  used_ = n;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,270 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+template<class A, class T>
+mp_int<A,T>::mp_int()
+:
+  digits_(0),
+  used_(0),
+  capacity_(0),
+  sign_(1)
+{
+}
+
+template<class A, class T>
+template<typename IntegralT>
+mp_int<A,T>::mp_int(
+    IntegralT b,
+    typename enable_if<is_integral<IntegralT> >::type*)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  detail::integral_ops<IntegralT>::assign(*this, b);
+}
+
+template<class A, class T>
+template<typename RandomAccessIterator>
+void mp_int<A,T>::init(RandomAccessIterator c, RandomAccessIterator last)
+{
+  assert(used_ == 0);
+
+  if (c == last)
+  {
+    sign_ = 1;
+    return;
+  }
+
+  int sign;
+
+  if (*c == '-')
+  {
+    ++c;
+    sign = -1;
+  }
+  else
+  {
+    if (*c == '+')
+      ++c;
+    sign = 1;
+  }
+ 
+  // detect the radix
+  unsigned int radix;
+  
+  if (c != last)
+  {
+    if (*c == '0') // octal
+    {
+      ++c;
+      if (c != last && (*c == 'x' || *c == 'X')) // hex
+      {
+        radix = 16;
+        ++c;
+      }
+      else
+      {
+        radix = 8;
+        --c; // keep the zero, necessary for mp_int("0")
+      }
+    }
+    else // decimal
+      radix = 10;
+  }
+  else
+    throw std::invalid_argument("mp_int ctor: malformed string");
+
+  sign_ = sign;
+
+  from_string(c, last, radix);
+}
+
+template<class A, class T>
+template<typename RandomAccessIterator>
+void mp_int<A,T>::init(RandomAccessIterator c,
+                       RandomAccessIterator last,
+                       std::ios_base::fmtflags f)
+{
+  assert(used_ == 0);
+
+  if (c == last)
+  {
+    sign_ = 1;
+    return;
+  }
+
+  if (*c == '-')
+  {
+    sign_ = -1;
+    ++c;
+  }
+  else
+  {
+    if (f & std::ios_base::showpos)
+    {
+      if (*c == '+')
+        ++c;
+      else
+        throw std::invalid_argument("mp_int<>::init: expected a '+' sign");
+    }
+    sign_ = 1;
+  }
+  
+  const bool uppercase = f & std::ios_base::uppercase;
+  const bool showbase  = f & std::ios_base::showbase;
+
+  bool bad_prefix = false;
+  unsigned radix;
+
+  if (f & std::ios_base::hex)
+  {
+    if (showbase)
+    {
+      if (*c == '0')
+        ++c;
+      else
+        bad_prefix = true;
+      if (*c == 'x' || (*c == 'X' && uppercase))
+        ++c;
+      else
+        bad_prefix = true;
+    }
+    radix = 16;
+  }
+  else if (f & std::ios_base::oct)
+  {
+    if (showbase)
+    {
+      if (*c == '0')
+        ++c;
+      else
+        bad_prefix = true;
+    }
+    radix = 8;
+  }
+  else if (f & std::ios_base::dec)
+    radix = 10;
+  else
+    throw std::invalid_argument("mp_int<>::init: unknown radix");
+
+  if (bad_prefix)
+    throw std::invalid_argument("mp_int<>::init: bad radix prefix");
+
+  from_string(c, last, radix);
+}
+
+
+template<class A, class T>
+template<typename RandomAccessIterator>
+mp_int<A,T>::mp_int(RandomAccessIterator first, RandomAccessIterator last)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  init(first, last);
+}
+
+template<class A, class T>
+mp_int<A,T>::mp_int(const char* s)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  init(s, s + std::strlen(s));
+}
+
+template<class A, class T>
+mp_int<A,T>::mp_int(const char* s, std::ios_base::fmtflags f)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  init(s, s + std::strlen(s), f);
+}
+
+
+#ifndef BOOST_NO_CWCHAR
+template<class A, class T>
+mp_int<A,T>::mp_int(const wchar_t* s)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  init(s, s + std::wcslen(s));
+}
+
+  template<class A, class T>
+mp_int<A,T>::mp_int(const wchar_t* s, std::ios_base::fmtflags f)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  init(s, s + std::wcslen(s), f);
+}
+#endif
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+mp_int<A,T>::mp_int(const std::basic_string<charT,traits,Alloc>& s)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  init(s.begin(), s.end());
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+mp_int<A,T>::mp_int(const std::basic_string<charT,traits,Alloc>& s,
+                    std::ios_base::fmtflags f)
+:
+  digits_(0),
+  used_(0),
+  capacity_(0)
+{
+  init(s.begin(), s.end(), f);
+}
+
+
+template<class A, class T>
+mp_int<A,T>::mp_int(const mp_int& copy)
+{
+  digits_ = this->allocate(copy.used_);
+  std::memcpy(digits_, copy.digits_, copy.used_ * sizeof(digit_type));
+  used_ = copy.used_;
+  capacity_ = copy.used_;
+  sign_ = copy.sign_;
+}
+
+#ifdef BOOST_HAS_RVALUE_REFS
+template<class A, class T>
+mp_int<A,T>::mp_int(mp_int&& copy)
+:
+  digits_(copy.digits_),
+  used_(copy.used_),
+  capacity_(copy.capacity_),
+  sign_(copy.sign_)
+{
+  copy.digits_ = 0;
+  copy.used_ = 0;
+  copy.capacity_ = 0;
+  copy.sign_ = 1;
+}
+#endif
+
+
+template<class A, class T>
+mp_int<A,T>::~mp_int()
+{
+  this->deallocate(digits_, capacity_);
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/detail/asm/x86/gnu_386_primitive_ops.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/asm/x86/gnu_386_primitive_ops.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,75 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+template
+struct primitive_ops<unsigned int, unsigned int, std::size_t>
+{
+  typedef unsigned int dword;
+  static unsigned int add_digits(dword* dst, const dword* y, std::size_t n);
+  static unsigned int subtract_digits(dword* dst, const dword* y, std::size_t n);
+};
+
+
+template
+inline
+unsigned int
+primitive_ops<unsigned int, unsigned int, std::size_t>::
+add_digits(unsigned int* x, const unsigned int* y, std::size_t n)
+{
+  unsigned int carry = 0;
+ 
+  __asm__ __volatile__(
+      "clc                \n\t"
+    "0:                   \n\t"
+      "mov (%[y]), %%eax  \n\t"
+      "adc %%eax, (%[x])  \n\t"
+      "lea 4(%[y]), %[y]  \n\t" // increment pointer
+      "lea 4(%[x]), %[x]  \n\t" // increment pointer
+    "loop 0b              \n\t"
+      "adc $0, %[carry]       "
+    :
+      [carry] "=m" (carry)
+    :
+      [y] "r" (y),
+      [x] "r" (x),
+      [n] "c" (n)
+    :
+      "cc", "memory", "%eax"
+    );
+
+  return carry;
+}
+
+
+template
+inline
+unsigned int
+primitive_ops<unsigned int, unsigned int, std::size_t>::
+subtract_digits(unsigned int* x, const unsigned int* y, std::size_t n)
+{
+  unsigned int carry = 0;
+
+  __asm__ __volatile__(
+      "clc                \n\t"
+    "0:                   \n\t"
+      "mov (%[y]), %%eax  \n\t"
+      "sbb %%eax, (%[x])  \n\t"
+      "lea 4(%[y]), %[y]  \n\t"
+      "lea 4(%[x]), %[x]  \n\t"
+    "loop 0b              \n\t"
+      "adc $0, %[carry]       "
+    :
+      [carry] "=m" (carry)
+    :
+      [y] "r" (y),
+      [x] "r" (x),
+      [n] "c" (n)
+    :
+      "cc", "memory", "%eax"
+    );
+
+  return carry;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,708 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_DETAIL_INTEGRAL_OPS_HPP
+#define BOOST_MP_MATH_MP_INT_DETAIL_INTEGRAL_OPS_HPP
+
+#include <boost/static_assert.hpp>
+#include <boost/mpl/greater.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/mp_math/mp_int/detail/meta_math.hpp>
+
+// here we optimize interaction with built in integral types
+
+namespace boost {
+namespace mp_math {
+
+template<class A, class T>
+struct mp_int;
+
+namespace detail {
+
+
+template<
+  typename IntegralT,
+  class MpInt,
+  bool is_signed = std::numeric_limits<IntegralT>::is_signed
+>
+struct integral_ops_impl
+{};
+
+
+template<
+  typename IntegralT,
+  class MpInt
+>
+struct integral_ops_impl<IntegralT, MpInt, false>
+{
+  static void assign  (MpInt& lhs, IntegralT rhs);
+
+  static bool equal   (const MpInt& lhs, IntegralT rhs);
+  static bool less    (const MpInt& lhs, IntegralT rhs);
+  
+  static void add     (MpInt& lhs, IntegralT rhs);
+  static void subtract(MpInt& lhs, IntegralT rhs);
+  static void multiply(MpInt& lhs, IntegralT rhs);
+  static void divide  (MpInt& lhs, IntegralT rhs);
+  static void modulo  (MpInt& lhs, IntegralT rhs);
+
+  static void bitwise_or (MpInt& lhs, IntegralT rhs);
+  static void bitwise_and(MpInt& lhs, IntegralT rhs);
+  static void bitwise_xor(MpInt& lhs, IntegralT rhs);
+
+private:
+
+  static const typename MpInt::size_type q =
+    std::numeric_limits<IntegralT>::digits / (MpInt::valid_bits + 1) + 1;
+
+  static bool equal_to_integral_type(const MpInt& x, IntegralT y)
+  {
+    try
+    {
+      return x.template to_integral<IntegralT>() == y;
+    }
+    catch (const std::overflow_error&)
+    {
+      return false;
+    }
+  }
+};
+
+
+template<
+  typename IntegralT,
+  class MpInt
+>
+struct integral_ops_impl<IntegralT, MpInt, true>
+{
+  static void assign  (MpInt& lhs, IntegralT rhs);
+
+  static bool equal   (const MpInt& lhs, IntegralT rhs);
+  static bool less    (const MpInt& lhs, IntegralT rhs);
+  
+  static void add     (MpInt& lhs, IntegralT rhs);
+  static void subtract(MpInt& lhs, IntegralT rhs);
+  static void multiply(MpInt& lhs, IntegralT rhs);
+  static void divide  (MpInt& lhs, IntegralT rhs);
+  static void modulo  (MpInt& lhs, IntegralT rhs);
+
+  static void bitwise_or (MpInt& lhs, IntegralT rhs);
+  static void bitwise_and(MpInt& lhs, IntegralT rhs);
+  static void bitwise_xor(MpInt& lhs, IntegralT rhs);
+
+private:
+
+  typedef typename make_unsigned<IntegralT>::type unsigned_type;
+
+  static const typename MpInt::size_type q =
+    std::numeric_limits<IntegralT>::digits + (MpInt::valid_bits - 1)
+    / MpInt::valid_bits;
+
+  static bool equal_to_integral_type(const MpInt& x, IntegralT y)
+  {
+    try
+    {
+      return x.template to_integral<IntegralT>() == y;
+    }
+    catch (const std::overflow_error&)
+    {
+      return false;
+    }
+  }
+};
+
+
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::assign(MpInt& lhs, IntegralT rhs)
+{
+  lhs.zero();
+  
+  if (rhs <= MpInt::digit_max)
+    lhs[0] = rhs;
+  else
+  {
+    typedef typename MpInt::digit_type digit_type;
+    static const int ud = std::numeric_limits<IntegralT>::digits;
+    static const int dd = MpInt::valid_bits;
+    static const int m = dd < ud ? dd : ud;
+    static const int h = m / 2;
+    /* set h bits at a time */
+    for (int i = 0; i < ud / h; ++i)
+    {
+      /* shift the number up h bits */
+      lhs <<= h;
+      // TODO optimize shift. only need to call grow_capacity once here
+      // then use lower level shift_left(lhs.digits_, h);
+
+      /* OR in the top h bits of the source */
+      lhs[0] |= (rhs >> (ud-h)) & (power<IntegralT,2,h>::value - 1);
+
+      /* shift the source up to the next h bits */
+      rhs <<= h;
+    }
+    lhs.clamp();
+  }
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::assign(MpInt& lhs, IntegralT rhs)
+{
+  int sign;
+  unsigned_type tmp;
+  if (rhs >= 0)
+  {
+    sign = 1;
+    tmp = rhs;
+  }
+  else
+  {
+    sign = -1;
+    // XXX using unary - may lose information on platforms without two's
+    // complement binary representation of integers. This conversion is well
+    // defined only within the minimum guaranteed integral limits given by the
+    // standard. In the functions below we use this several times again.
+    tmp = -rhs;
+  }
+
+  integral_ops_impl<unsigned_type,MpInt>::assign(lhs, tmp);
+
+  lhs.set_sign(sign);
+}
+
+template<typename IntegralT, class MpInt>
+bool
+integral_ops_impl<IntegralT, MpInt, false>::equal(const MpInt& lhs, IntegralT rhs)
+{
+  if (lhs.size() > q)
+    return false;
+  
+  return equal_to_integral_type(lhs, rhs);
+}
+
+template<typename IntegralT, class MpInt>
+bool
+integral_ops_impl<IntegralT, MpInt, true>::equal(const MpInt& lhs, IntegralT rhs)
+{
+  const int r_sign = rhs < 0 ? -1 : 1;
+  
+  if (lhs.sign() != r_sign)
+    return false;
+
+  if (lhs.size() > q)
+    return false;
+
+  return equal_to_integral_type(lhs, rhs);
+}
+
+template<typename IntegralT, class MpInt>
+bool
+integral_ops_impl<IntegralT, MpInt, false>::less(const MpInt& lhs, IntegralT rhs)
+{
+  if (lhs.sign() == -1)
+    return true;
+
+  if (lhs.size() > q)
+    return false;
+
+  return lhs.template to_integral<IntegralT>() < rhs;
+}
+
+template<typename IntegralT, class MpInt>
+bool
+integral_ops_impl<IntegralT, MpInt, true>::less(const MpInt& lhs, IntegralT rhs)
+{
+  if (lhs.sign() == -1 && rhs >= 0)
+    return true;
+  
+  if (lhs.sign() == 1 && rhs < 0)
+    return false;
+
+  if (lhs.size() > q)
+    return false;
+
+  return lhs.template to_integral<IntegralT>() < rhs;
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::add(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+    lhs.add_digit(static_cast<typename MpInt::digit_type>(rhs));
+  else
+    lhs += MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::add(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs >= 0)
+  {
+    if (static_cast<unsigned_type>(rhs) <= MpInt::digit_max)
+    {
+      lhs.add_digit(static_cast<typename MpInt::digit_type>(rhs));
+      return;
+    }
+  }
+  else
+  {
+    const unsigned_type tmp(-rhs);
+    if (tmp <= MpInt::digit_max)
+    {
+      lhs.sub_digit(static_cast<typename MpInt::digit_type>(tmp));
+      return;
+    }
+  }
+
+  // TODO: we're touching the allocator below...
+  // we can probably do better maybe we can store the Integral to a
+  // digits array on the stack, then use the addition algorithm to
+  // add the numbers, or create a fixed precision int that can live on
+  // the stack and write operator += to let mp_int interact with fp_int
+  // the same goes for all other ops in this file that do this kind of stuff.
+  lhs += MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::subtract(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+    lhs.sub_digit(static_cast<typename MpInt::digit_type>(rhs));
+  else
+    lhs -= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::subtract(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs >= 0)
+  {
+    if (static_cast<unsigned_type>(rhs) <= MpInt::digit_max)
+    {
+      lhs.sub_digit(static_cast<typename MpInt::digit_type>(rhs));
+      return;
+    }
+  }
+  else
+  {
+    const unsigned_type tmp(-rhs);
+    if (tmp <= MpInt::digit_max)
+    {
+      lhs.add_digit(static_cast<typename MpInt::digit_type>(tmp));
+      return;
+    }
+  }
+
+  lhs -= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::multiply(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+    lhs.multiply_by_digit(static_cast<typename MpInt::digit_type>(rhs));
+  else
+    lhs *= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::multiply(MpInt& lhs, IntegralT rhs)
+{
+  int sign;
+  unsigned_type tmp;
+  if (rhs >= 0)
+  {
+    sign = 1;
+    tmp = rhs;
+  }
+  else
+  {
+    sign = -1;
+    tmp = -rhs;
+  }
+
+  if (tmp <= MpInt::digit_max)
+  {
+    lhs.multiply_by_digit(static_cast<typename MpInt::digit_type>(tmp));
+    lhs.set_sign(lhs.sign() * sign);
+  }
+  else
+    lhs *= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::divide(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+    lhs.divide_by_digit(rhs);
+  else
+    lhs /= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::divide(MpInt& lhs, IntegralT rhs)
+{
+  int sign;
+  unsigned_type tmp;
+  if (rhs >= 0)
+  {
+    sign = 1;
+    tmp = rhs;
+  }
+  else
+  {
+    sign = -1;
+    tmp = -rhs;
+  }
+
+  if (tmp <= MpInt::digit_max)
+  {
+    lhs.divide_by_digit(static_cast<typename MpInt::digit_type>(tmp));
+    lhs.set_sign(lhs.sign() / sign);
+  }
+  else
+    lhs /= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::modulo(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+  {
+    lhs[0] = lhs.divide_by_digit(rhs);
+    lhs.set_size(1);
+  }
+  else
+    lhs %= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::modulo(MpInt& lhs, IntegralT rhs)
+{
+  unsigned_type tmp;
+  if (rhs >= 0)
+    tmp = rhs;
+  else
+    tmp = -rhs;
+
+  if (tmp <= MpInt::digit_max)
+  {
+    lhs[0] = lhs.divide_by_digit(static_cast<typename MpInt::digit_type>(tmp));
+    lhs.set_size(1);
+  }
+  else
+    lhs %= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::bitwise_or(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+    lhs[0] |= rhs;
+  else
+    lhs |= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::bitwise_or(MpInt& lhs, IntegralT rhs)
+{
+  // we care only about the absolute value of rhs
+  unsigned_type tmp;
+  if (rhs >= 0)
+    tmp = rhs;
+  else
+    tmp = -rhs;
+
+  if (tmp <= MpInt::digit_max)
+    lhs[0] |= static_cast<typename MpInt::digit_type>(tmp);
+  else
+    lhs |= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::bitwise_and(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+    lhs[0] &= rhs;
+  else
+    lhs &= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::bitwise_and(MpInt& lhs, IntegralT rhs)
+{
+  unsigned_type tmp;
+  if (rhs >= 0)
+    tmp = rhs;
+  else
+    tmp = -rhs;
+
+  if (tmp <= MpInt::digit_max)
+    lhs[0] &= static_cast<typename MpInt::digit_type>(tmp);
+  else
+    lhs &= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, false>::bitwise_xor(MpInt& lhs, IntegralT rhs)
+{
+  if (rhs <= MpInt::digit_max)
+    lhs[0] ^= rhs;
+  else
+    lhs ^= MpInt(rhs);
+}
+
+template<typename IntegralT, class MpInt>
+void
+integral_ops_impl<IntegralT, MpInt, true>::bitwise_xor(MpInt& lhs, IntegralT rhs)
+{
+  unsigned_type tmp;
+  if (rhs >= 0)
+    tmp = rhs;
+  else
+    tmp = -rhs;
+
+  if (tmp <= MpInt::digit_max)
+    lhs[0] ^= static_cast<typename MpInt::digit_type>(tmp);
+  else
+    lhs ^= MpInt(rhs);
+}
+
+
+
+
+
+template<
+  typename IntegralT,
+  class MpInt,
+  bool is_signed = std::numeric_limits<IntegralT>::is_signed,
+  bool is_larger = (std::numeric_limits<IntegralT>::digits > MpInt::valid_bits)
+>
+struct integral_ops2
+{};
+
+
+template<typename IntegralT, class MpInt>
+struct integral_ops2<IntegralT, MpInt, true, true>
+{
+  typedef std::numeric_limits<IntegralT> integral_type_limits;
+  typedef typename make_unsigned<IntegralT>::type unsigned_type;
+  
+  static IntegralT to_integral(const MpInt& x);
+};
+
+template<typename IntegralT, class MpInt>
+struct integral_ops2<IntegralT, MpInt, true, false>
+{
+  typedef std::numeric_limits<IntegralT> integral_type_limits;
+  typedef typename make_unsigned<IntegralT>::type unsigned_type;
+  
+  static IntegralT to_integral(const MpInt& x);
+};
+
+template<typename IntegralT, class MpInt>
+struct integral_ops2<IntegralT, MpInt, false, true>
+{
+  typedef std::numeric_limits<IntegralT> integral_type_limits;
+  
+  static IntegralT apply_shift(const MpInt& x);
+  static IntegralT to_integral(const MpInt& x);
+};
+
+template<typename IntegralT, class MpInt>
+struct integral_ops2<IntegralT, MpInt, false, false>
+{
+  typedef std::numeric_limits<IntegralT> integral_type_limits;
+  
+  static IntegralT apply_shift(const MpInt& x);
+  static IntegralT to_integral(const MpInt& x);
+};
+
+
+template<typename IntegralT, class MpInt>
+IntegralT integral_ops2<IntegralT, MpInt, true, true>::to_integral(const MpInt& x)
+{
+  if (x.size() == 1)
+  {
+    if (x.digits()[0] <= integral_type_limits::max())
+      return static_cast<IntegralT>(x.sign()) *
+             static_cast<IntegralT>(x[0]);
+    throw std::overflow_error(
+        "to_integral: integral type does not have enough precision to hold result");
+  }
+
+  const unsigned_type tmp = integral_ops2<unsigned_type, MpInt>::apply_shift(x);
+
+  return static_cast<IntegralT>(x.sign()) * static_cast<IntegralT>(tmp);
+}
+
+template<typename IntegralT, class MpInt>
+IntegralT integral_ops2<IntegralT, MpInt, true, false>::to_integral(const MpInt& x)
+{
+  if (x.size() == 1)
+    return static_cast<IntegralT>(x.sign()) * static_cast<IntegralT>(x[0]);
+
+  const unsigned_type tmp = integral_ops2<unsigned_type, MpInt>::apply_shift(x);
+
+  return static_cast<IntegralT>(x.sign()) * static_cast<IntegralT>(tmp);
+}
+
+template<typename IntegralT, class MpInt>
+IntegralT integral_ops2<IntegralT, MpInt, false, true>::apply_shift(const MpInt& x)
+{
+  int shift_count = 0;
+  IntegralT tmp = 0;
+  
+  for (typename MpInt::const_reverse_iterator digit = x.rbegin();
+      digit != x.rend(); ++digit)
+  {
+    tmp <<= MpInt::valid_bits;
+    if (shift_count++ * MpInt::valid_bits > integral_type_limits::digits)
+      throw std::overflow_error(
+          "to_integral: integral type does not have enough precision to hold result");
+    tmp |= *digit & (power<IntegralT,2,MpInt::valid_bits>::value - 1);
+  }
+
+  return tmp;
+}
+
+template<typename IntegralT, class MpInt>
+IntegralT integral_ops2<IntegralT, MpInt, false, true>::to_integral(const MpInt& x)
+{
+  if (x.sign() == 1)
+  {
+    if (x.size() == 1 && x[0] <= integral_type_limits::max())
+      return static_cast<IntegralT>(x[0]);
+  }
+  else
+    throw std::overflow_error(
+        "to_integral: cannot convert negative number to unsigned integral type");
+  
+  return apply_shift(x);
+}
+
+template<typename IntegralT, class MpInt>
+IntegralT integral_ops2<IntegralT, MpInt, false, false>::apply_shift(const MpInt&)
+{
+  throw std::overflow_error(
+      "to_integral: integral type does not have enough precision to hold result");
+}
+
+template<typename IntegralT, class MpInt>
+IntegralT integral_ops2<IntegralT, MpInt, false, false>::to_integral(const MpInt& x)
+{
+  if (x.size() == 1)
+    return static_cast<IntegralT>(x[0]);
+  else
+    return apply_shift(x);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+
+template<typename IntegralT>
+struct integral_ops
+{
+  BOOST_STATIC_ASSERT(boost::is_integral<IntegralT>::value);
+
+  template<class A, class T>
+  static IntegralT convert(const mp_int<A,T>& x)
+  {
+    return integral_ops2<IntegralT, mp_int<A,T> >::to_integral(x);
+  }
+  
+  template<class A, class T>
+  static void assign(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::assign(lhs, rhs);
+  }
+  
+  template<class A, class T>
+  static bool equal(const mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    return integral_ops_impl<IntegralT, mp_int<A,T> >::equal(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static bool less(const mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    return integral_ops_impl<IntegralT, mp_int<A,T> >::less(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static void add(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::add(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static void subtract(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::subtract(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static void multiply(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::multiply(lhs, rhs);
+  }
+  
+  template<class A, class T>
+  static void divide(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::divide(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static void modulo(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::modulo(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static void bitwise_or(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::bitwise_or(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static void bitwise_and(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::bitwise_and(lhs, rhs);
+  }
+
+  template<class A, class T>
+  static void bitwise_xor(mp_int<A,T>& lhs, IntegralT rhs)
+  {
+    integral_ops_impl<IntegralT, mp_int<A,T> >::bitwise_xor(lhs, rhs);
+  }
+};
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+
Added: sandbox/mp_math/boost/mp_math/mp_int/detail/meta_math.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/meta_math.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,74 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_DETAIL_META_MATH_HPP
+#define BOOST_MP_MATH_MP_INT_DETAIL_META_MATH_HPP
+
+#include <boost/config.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+
+// power -----------------------------------------------------------------------
+
+template<
+	typename IntegralT,
+	IntegralT X, IntegralT Y,
+	IntegralT Result = X, IntegralT Count = 0, bool EndRecursion = Count == Y-1>
+struct power_impl
+{
+	static const IntegralT value =
+		power_impl<IntegralT, X, Y, Result*X, Count + 1>::value;
+};
+
+template<
+	typename IntegralT,
+	IntegralT X, IntegralT Y,
+	IntegralT Result, IntegralT Count>
+struct power_impl<IntegralT, X, Y, Result, Count, true>
+{
+	static const IntegralT value = Result;
+};
+
+
+// calculate x to the power of y
+template<typename IntegralT, IntegralT X, IntegralT Y>
+struct power
+{
+	static const IntegralT value = power_impl<IntegralT,X,Y>::value;
+};
+
+
+
+// logarithm to base 2 ---------------------------------------------------------
+
+template<typename T, T Temp, T Count = 1, bool continue_loop = (Temp > 1)>
+struct binary_log_impl
+{
+  static const T value = binary_log_impl<T, (Temp >> 1), Count + 1>::value;
+};
+
+template<typename T, T Temp, T Count>
+struct binary_log_impl<T, Temp, Count, false>
+{
+  static const T value = Count;
+};
+
+template<typename T, T Val>
+struct binary_log
+{
+  static const T value = binary_log_impl<T, Val>::value;
+};
+
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
Added: sandbox/mp_math/boost/mp_math/mp_int/detail/prime_tab.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/prime_tab.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,95 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_DETAIL_PRIME_TAB_HPP
+#define BOOST_MP_MATH_DETAIL_PRIME_TAB_HPP
+
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+
+template<
+  typename T = unsigned short // this exists solely to keep this header-only
+>
+struct prime_tab_impl
+{
+  static const T values[];
+};
+
+template<typename T>
+const T prime_tab_impl<T>::values[] =
+{
+  /*0x2*/ 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+  // for greater than 8bit digit_type:
+                                                          0x0083,
+  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+};
+
+
+template<
+  typename DigitT,
+  bool is_small =
+    std::numeric_limits<DigitT>::digits ==
+    std::numeric_limits<unsigned char>::digits
+>
+struct prime_tab
+:
+  prime_tab_impl<>
+{
+  static const int num_primes = 255;
+};
+
+// XXX For an unsigned char type that is larger than 8 bits, num_primes will be
+// wrong. Oh well.
+template<typename DigitT>
+struct prime_tab<DigitT,true>
+:
+  prime_tab_impl<>
+{
+  static const int num_primes = 30;
+};
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
Added: sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,533 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_DETAIL_PRIMITIVE_OPS
+#define BOOST_MP_MATH_MP_INT_DETAIL_PRIMITIVE_OPS
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+
+// this struct contains some basic arithmetic algorithms
+// which can be implemented via assembly rather easily
+
+template<typename DigitT, typename WordT, typename SizeT>
+struct basic_primitive_ops
+{
+  typedef DigitT digit_type;
+  typedef WordT  word_type;
+  typedef SizeT  size_type;
+  
+  static const word_type digit_bits = std::numeric_limits<digit_type>::digits;
+
+  // ADD ------------------------------------
+
+  // add x to the digits in y and store result in z
+  // ylen must be > 0
+  // returns: the last carry (it will not get stored in z)
+  static digit_type add_single_digit(digit_type* z,
+                                     const digit_type* y, size_type ylen,
+                                     digit_type x);
+
+  // z = x + y, returns last carry
+  static digit_type add_digits(digit_type* z,
+                               const digit_type* x,
+                               const digit_type* y,
+                               size_type num);
+
+  // ripples the carry c up through n digits of x and stores results in z
+  // returns the number of digits the carry rippled through and stores the last
+  // carry in c. If there isn't a last carry then c will be 0.
+  static size_type ripple_carry(digit_type* z,
+                                const digit_type* x,
+                                size_type n,
+                                digit_type& c);
+
+  // z = x + y, where xlen >= ylen
+  // z and x may not overlap
+  static void add_magnitude(digit_type* z,
+                            const digit_type* x, size_type xlen,
+                            const digit_type* y, size_type ylen);
+
+  // SUB ------------------------------------
+
+  // subtracts x from the digits in y and store result in z
+  static void subtract_single_digit(digit_type* z,
+                                    const digit_type* y, size_type ylen,
+                                    digit_type x);
+
+  // z = x - y, returns last borrow
+  static digit_type subtract_digits(digit_type* z,
+                                    const digit_type* x,
+                                    const digit_type* y,
+                                    size_type num);
+
+  // ripples the borrow up through n digits of x and stores results in z
+  // returns the number of digits the borrow rippled through
+  static size_type ripple_borrow(digit_type* z,
+                                 const digit_type* x,
+                                 size_type n,
+                                 digit_type borrow);
+
+  // z = x - y, where x >= y
+  static void sub_smaller_magnitude(digit_type* z,
+                                    const digit_type* x, size_type xlen,
+                                    const digit_type* y, size_type ylen);
+
+  // MUL ------------------------------------
+
+  // multiply y of length ylen with x and store result in z
+  // returns: the last carry (it will not get stored in z)
+  static digit_type multiply_by_digit(digit_type* z,
+                                      const digit_type* y, size_type ylen,
+                                      digit_type x);
+
+  // z = x * y
+  static void classic_mul(digit_type* z, const digit_type* x, size_type x_size,
+                                         const digit_type* y, size_type y_size);
+
+  // z = x * y; precondition: x_size >= y_size
+  static void comba_mul(digit_type* z, const digit_type* x, size_type x_size,
+                                       const digit_type* y, size_type y_size);
+
+  // z = x * y; for numbers of the same size
+  static void comba_mul(digit_type* z,
+                        const digit_type* x,
+                        const digit_type* y, size_type xy_size);
+  
+  // SQR ------------------------------------
+
+  // z = x * x;
+  static void comba_sqr(digit_type* z, const digit_type* x, size_type x_size);
+};
+
+
+
+template<typename D, typename W, typename S>
+inline
+typename basic_primitive_ops<D,W,S>::digit_type
+basic_primitive_ops<D,W,S>::add_single_digit(digit_type* z,
+                                             const digit_type* y, size_type ylen,
+                                             digit_type x)
+{
+  word_type carry = static_cast<word_type>(*y++) + x;
+  *z++ = static_cast<digit_type>(carry);
+  carry >>= digit_bits;
+
+  while (carry && --ylen)
+  {
+    carry += static_cast<word_type>(*y++);
+    *z++ = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+
+  return static_cast<digit_type>(carry);
+}
+
+
+template<typename D, typename W, typename S>
+inline
+typename basic_primitive_ops<D,W,S>::digit_type
+basic_primitive_ops<D,W,S>::add_digits(digit_type* z,
+                                       const digit_type* x,
+                                       const digit_type* y, size_type n)
+{
+  word_type carry = 0;
+
+  while (n--)
+  {
+    carry += static_cast<word_type>(*x++) + static_cast<word_type>(*y++);
+    *z++ = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+
+  return static_cast<digit_type>(carry);
+}
+
+template<typename D, typename W, typename S>
+inline
+typename basic_primitive_ops<D,W,S>::size_type
+basic_primitive_ops<D,W,S>::ripple_carry(digit_type* z,
+                                         const digit_type* x,
+                                         size_type n,
+                                         digit_type& carry)
+{
+  word_type c = carry;
+  size_type i = 0;
+
+  for (; c && (i < n); ++i)
+  {
+    c += static_cast<word_type>(*x++);
+    *z++ = static_cast<digit_type>(c);
+    c >>= digit_bits;
+  }
+
+  carry = static_cast<digit_type>(c);
+  
+  return i;
+}
+
+template<typename D, typename W, typename S>
+inline
+void basic_primitive_ops<D,W,S>::add_magnitude(
+    digit_type* z,
+    const digit_type* x, size_type xlen,
+    const digit_type* y, size_type ylen)
+{
+  digit_type carry = add_digits(z, x, y, ylen);
+  
+  size_type n = ripple_carry(z + ylen, x + ylen, xlen - ylen, carry);
+
+  if (carry)
+    *(z + n++) = carry; // wrong
+  
+  const size_type cur = ylen + n;
+  if (cur < xlen)
+    std::memcpy(z + cur, x + cur, (xlen - cur) * sizeof(digit_type));
+}
+
+template<typename D, typename W, typename S>
+inline
+void
+basic_primitive_ops<D,W,S>::subtract_single_digit(digit_type* z,
+                                                  const digit_type* y, size_type ylen,
+                                                  digit_type x)
+{
+  word_type borrow = static_cast<word_type>(*y++) - x;
+  *z++ = static_cast<digit_type>(borrow);
+  borrow >>= static_cast<word_type>(std::numeric_limits<word_type>::digits - 1);
+
+  while (borrow && --ylen)
+  {
+    borrow = static_cast<word_type>(*y++) - borrow;
+    *z++   = static_cast<digit_type>(borrow);
+    borrow >>= static_cast<word_type>(std::numeric_limits<word_type>::digits - 1);
+  }
+}
+
+template<typename D, typename W, typename S>
+inline
+typename basic_primitive_ops<D,W,S>::digit_type
+basic_primitive_ops<D,W,S>::subtract_digits(digit_type* z,
+                                            const digit_type* x,
+                                            const digit_type* y,
+                                            size_type n)
+{
+  word_type borrow = 0;
+
+  while (n--)
+  {
+    borrow = static_cast<word_type>(*x++) - static_cast<word_type>(*y++) - borrow;
+    *z++   = static_cast<digit_type>(borrow);
+    borrow >>= std::numeric_limits<word_type>::digits - 1;
+  }
+
+  return static_cast<digit_type>(borrow);
+}
+
+template<typename D, typename W, typename S>
+inline
+typename basic_primitive_ops<D,W,S>::size_type
+basic_primitive_ops<D,W,S>::ripple_borrow(digit_type* z,
+                                          const digit_type* x,
+                                          size_type n,
+                                          digit_type borrow)
+{
+  word_type b = borrow;
+  size_type i = 0;
+  for (; b && (i < n); ++i)
+  {
+    b    = static_cast<word_type>(*x++) - b;
+    *z++ = static_cast<digit_type>(b);
+    b >>= std::numeric_limits<word_type>::digits - 1;
+  }
+  
+  return i;
+}
+
+template<typename D, typename W, typename S>
+inline
+void basic_primitive_ops<D,W,S>::sub_smaller_magnitude(
+    digit_type* z,
+    const digit_type* x, size_type xlen,
+    const digit_type* y, size_type ylen)
+{
+  const digit_type borrow = subtract_digits(z, x, y, ylen);
+
+  const size_type n = ripple_borrow(z + ylen, x + ylen, xlen - ylen, borrow);
+
+  const size_type cur = ylen + n;
+  std::memcpy(z + cur, x + cur, (xlen - cur) * sizeof(digit_type));
+}
+
+
+template<typename D, typename W, typename S>
+inline
+typename basic_primitive_ops<D,W,S>::digit_type
+basic_primitive_ops<D,W,S>::multiply_by_digit(digit_type* z,
+                                              const digit_type* y, size_type ylen,
+                                              digit_type x)
+{
+  digit_type carry = 0;
+
+  while (ylen--)
+  {
+    const word_type tmp = static_cast<word_type>(carry)
+                        + static_cast<word_type>(*y++)
+                        * static_cast<word_type>(x);
+    *z++ = static_cast<digit_type>(tmp);
+    carry = static_cast<digit_type>(tmp >> digit_bits);
+  }
+  return carry;
+}
+
+template<typename D, typename W, typename S>
+void
+basic_primitive_ops<D,W,S>::classic_mul(
+    digit_type* z, const digit_type* x, size_type x_size,
+                   const digit_type* y, size_type y_size)
+{
+  // phase 1
+  word_type tmp = static_cast<word_type>(x[0]) * static_cast<word_type>(y[0]);
+  z[0] = static_cast<digit_type>(tmp);
+  
+  for (size_type i = 1; i < x_size; ++i)
+  {
+    tmp = (tmp >> digit_bits)
+        + static_cast<word_type>(x[i])
+        * static_cast<word_type>(y[0]);
+    z[i] = static_cast<digit_type>(tmp);
+  }
+  
+  tmp >>= digit_bits;
+  z[x_size] = static_cast<digit_type>(tmp);
+  
+  // phase 2
+  for (size_type i = 1; i < y_size; ++i)
+  {
+    tmp = static_cast<word_type>(y[i])
+        * static_cast<word_type>(x[0])
+        + static_cast<word_type>(z[i]);
+    z[i] = static_cast<digit_type>(tmp);
+    
+    for (size_type j = 1; j < x_size; ++j)
+    {
+      tmp = (tmp >> digit_bits)
+          + static_cast<word_type>(y[i]) * static_cast<word_type>(x[j])
+          + static_cast<word_type>(z[i+j]);
+      z[i+j] = static_cast<digit_type>(tmp);
+    }
+    
+    tmp >>= digit_bits;
+    z[i + x_size] = static_cast<digit_type>(tmp);
+  }
+}
+
+
+// K = 2 ^ (alpha - (2*beta-1))
+// alpha = num bits of word_type, beta = num bits of digit_type
+// calculation works in 3 phases
+//                65432
+//              x   223
+//----------------------------------
+//              | 18  15 | 12  9  6
+//           12 | 10   8 |  6  4
+//        12 10 |  8   6 |  4 
+//              |        |    
+// phase:   3   |    2   |    1
+//
+// TODO handle too long columns => carry may overflow. This can happen if
+// digit_type is 8bit; in that case delegate to classic_mul routine in
+// operator *= (). Just check if (smaller number).used_ >= overflow_count.
+template<typename D, typename W, typename S>
+void
+basic_primitive_ops<D,W,S>::comba_mul(
+    digit_type* z, const digit_type* x, size_type x_size,
+                   const digit_type* y, size_type y_size)
+{
+  assert(x_size >= y_size);
+
+  const size_type k = x_size + y_size;
+
+  word_type acc = 0;  // accumulator in each column
+  word_type carry = 0;
+  
+  // phase 1
+  for (size_type i = 0; i < y_size; ++i)
+  {
+    for (size_type j = 0; j <= i; ++j)
+    {
+      const word_type r = static_cast<word_type>(y[j])
+                        * static_cast<word_type>(x[i-j]);
+      acc += r;
+      carry += acc >> digit_bits;
+      acc = static_cast<digit_type>(acc);
+    }
+    *z++ = static_cast<digit_type>(acc);
+    acc  = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+  
+  // phase 2
+  for (size_type i = 0; i < x_size - y_size; ++i)
+  {
+    size_type j = 0;
+    size_type m = y_size;
+    while (j < y_size)
+    {
+      const word_type r = static_cast<word_type>(y[j])
+                        * static_cast<word_type>(x[m+i]);
+      acc += r;
+      carry += acc >> digit_bits;
+      acc = static_cast<digit_type>(acc);
+      ++j; --m;
+    }
+    *z++ = static_cast<digit_type>(acc);
+    acc = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+  
+  // phase 3
+  for (size_type i = x_size; i < k - 1; ++i)
+  {
+    for (size_type j = y_size - (k - i - 1); j < y_size; ++j)
+    {
+      const word_type r = static_cast<word_type>(y[j])
+                        * static_cast<word_type>(x[i-j]);
+      acc += r;
+      carry += acc >> digit_bits;
+      acc = static_cast<digit_type>(acc);
+    }
+    *z++ = static_cast<digit_type>(acc);
+    acc  = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+  
+  *z = static_cast<digit_type>(acc);
+}
+
+template<typename D, typename W, typename S>
+void
+basic_primitive_ops<D,W,S>::comba_mul(digit_type* z,
+                                      const digit_type* x,
+                                      const digit_type* y, size_type xy_size)
+{
+  word_type acc = 0;  // accumulator for each column
+  word_type carry = 0;
+
+  // phase 1
+  for (size_type i = 0; i < xy_size; ++i)
+  {
+    for (size_type j = 0; j <= i; ++j)
+    {
+      const word_type r = static_cast<word_type>(x[j])
+                        * static_cast<word_type>(y[i-j]);
+      acc += r;
+      carry += acc >> digit_bits;
+      acc = static_cast<digit_type>(acc);
+    }
+    *z++ = static_cast<digit_type>(acc);
+    acc = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+
+  // phase 2
+  for (size_type i = xy_size; i < 2 * xy_size - 1; ++i)
+  {
+    for (size_type j = i - xy_size + 1; j < xy_size; ++j)
+    {
+      const word_type r = static_cast<word_type>(x[j])
+                        * static_cast<word_type>(y[i-j]);
+      acc += r;
+      carry += acc >> digit_bits;
+      acc = static_cast<digit_type>(acc);
+    }
+    *z++ = static_cast<digit_type>(acc);
+    acc = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+
+  *z = static_cast<digit_type>(acc);
+}
+
+template<typename D, typename W, typename S>
+void
+basic_primitive_ops<D,W,S>::comba_sqr(digit_type* z,
+                                      const digit_type* x,
+                                      size_type x_size)
+{
+  word_type acc = 0;  // accumulator for each column
+  word_type carry = 0;
+
+  // phase 1
+  for (size_type i = 0; i < x_size; ++i)
+  {
+    for (size_type j = 0; j <= i; ++j)
+    {
+      const word_type r = static_cast<word_type>(x[j])
+                        * static_cast<word_type>(x[i-j]);
+      acc += r;
+      carry += acc >> digit_bits;
+      acc = static_cast<digit_type>(acc);
+    }
+    *z++ = static_cast<digit_type>(acc);
+    acc = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+
+  // phase 2
+  for (size_type i = x_size; i < 2 * x_size - 1; ++i)
+  {
+    for (size_type j = i - x_size + 1; j < x_size; ++j)
+    {
+      const word_type r = static_cast<word_type>(x[j])
+                        * static_cast<word_type>(x[i-j]);
+      acc += r;
+      carry += acc >> digit_bits;
+      acc = static_cast<digit_type>(acc);
+    }
+    *z++ = static_cast<digit_type>(acc);
+    acc = static_cast<digit_type>(carry);
+    carry >>= digit_bits;
+  }
+
+  *z = static_cast<digit_type>(acc);
+}
+
+
+
+
+
+// This exists to ease development of primitive_ops specializations. If a
+// specialized function isn't available yet, the compiler will just choose the
+// inherited one. It also means that whenever we add a new function to
+// basic_primitive_ops no code will break since it will be available to all
+// specializations as well.
+template<typename D, typename W, typename S>
+struct primitive_ops : basic_primitive_ops<D,W,S>
+{};
+
+
+// Here we include primitive_ops specializations that use assembler
+
+#if defined(BOOST_MP_MATH_MP_INT_USE_ASM)
+  
+  #if defined(__GNU__)
+    #if defined(__386__)
+      #include <boost/mp_math/mp_int/detail/asm/x86/gnu_386_primitive_ops.hpp>
+    #endif
+  #endif
+
+#endif
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+
Added: sandbox/mp_math/boost/mp_math/mp_int/detail/string_conversion_constants.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/detail/string_conversion_constants.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,111 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_DETAIL_STRING_CONVERSION_CONSTANTS_HPP
+#define BOOST_MP_MATH_MP_INT_DETAIL_STRING_CONVERSION_CONSTANTS_HPP
+
+#include <boost/mp_math/mp_int/detail/meta_math.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+// radix 8, 10, 16
+
+
+template<
+  class MpInt,
+  typename MpInt::size_type Base,
+  typename MpInt::word_type Temp = 1,
+  typename MpInt::size_type Count = 0,
+  bool continue_loop = (Temp < MpInt::digit_max)
+>
+struct max_power_impl
+{
+  typedef max_power_impl<MpInt, Base, Temp * Base, Count + 1> result;
+  static const typename MpInt::size_type  value     = result::value;
+  static const typename MpInt::digit_type max_value = result::max_value;
+};
+
+template<
+  class MpInt,
+  typename MpInt::size_type Base,
+  typename MpInt::word_type Temp,
+  typename MpInt::size_type Count
+>
+struct max_power_impl<MpInt, Base, Temp, Count, false>
+{
+  static const typename MpInt::size_type  value     = Count - 1;
+  static const typename MpInt::digit_type max_value =
+    static_cast<typename MpInt::digit_type>(Temp / Base);
+};
+
+
+template<class MpInt, typename MpInt::size_type Base>
+struct max_power
+{
+  // convenience typedef ICEs on VC9 + SP1
+  //typedef max_power_impl<MpInt, Base> result;
+  static const typename MpInt::size_type  value     = max_power_impl<MpInt, Base>::value;
+  static const typename MpInt::digit_type max_value = max_power_impl<MpInt, Base>::max_value;
+};
+
+
+
+template<class MpInt, unsigned B>
+struct data
+{
+  typedef max_power<MpInt, B> x;
+  static const typename MpInt::size_type  max_power_          = x::value;
+  static const typename MpInt::digit_type max_power_value_    = x::max_value;
+  static const typename MpInt::size_type  radix_storage_bits_ =
+    binary_log<typename MpInt::size_type, B - 1>::value;
+};
+
+
+template<class MpInt>
+struct string_conversion_constants
+{
+  // maximum power of radix that fits into a digit_type
+  typename MpInt::size_type  max_power;
+  // the corresponding power value (=radix**max_power)
+  typename MpInt::digit_type max_power_value;
+  // how many bits do we need to store the value radix
+  typename MpInt::size_type  radix_storage_bits;
+
+  explicit string_conversion_constants(unsigned radix)
+  {
+    switch (radix)
+    {
+      case  8: *this = data<MpInt,  8>(); break;
+      case 10: *this = data<MpInt, 10>(); break;
+      case 16: *this = data<MpInt, 16>(); break;
+      default:
+        throw std::invalid_argument(
+            "mp_int<>::string_conversion_constants: unsupported radix used");
+    }
+  }
+
+  template<unsigned B>
+  string_conversion_constants& operator = (const data<MpInt, B>&)
+  {
+    max_power          = data<MpInt, B>::max_power_;
+    max_power_value    = data<MpInt, B>::max_power_value_;
+    radix_storage_bits = data<MpInt, B>::radix_storage_bits_;
+    return *this;
+  }
+};
+
+
+
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+
Added: sandbox/mp_math/boost/mp_math/mp_int/div.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/div.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,323 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+template<class A, class T>
+typename mp_int<A,T>::digit_type
+mp_int<A,T>::divide_by_digit(digit_type b)
+{
+  if (b == 0)
+    throw std::domain_error("mp_int::divide_by_digit: division by zero");
+
+  if (b == 1 || is_zero())
+    return 0;
+
+  const bool is_power_of_two = (b & (b-1)) == 0;
+  if (is_power_of_two)
+  {
+    for (int i = 0; i < valid_bits; ++i)
+    {
+      if (b == digit_type(1) << i)
+      {
+        const digit_type remainder = digits_[0] & ((digit_type(1) << i) - 1);
+        *this >>= i;
+        return remainder;
+      }
+    }
+  }
+
+  word_type w = 0;
+  for (reverse_iterator d = rbegin(); d != rend(); ++d)
+  {
+    w = (w << static_cast<word_type>(valid_bits)) | static_cast<word_type>(*d);
+    digit_type tmp;
+    if (w >= b)
+    {
+      tmp = static_cast<digit_type>(w / b);
+      w -= tmp * b;
+    }
+    else
+      tmp = 0;
+    *d = tmp;
+  }
+
+  clamp();
+  if (is_zero())
+    sign_ = 1;
+ 
+  return static_cast<digit_type>(w);
+}
+
+/* b = a/2 */
+template<class A, class T>
+void mp_int<A,T>::divide_by_2()
+{
+  digit_type carry = 0;
+  for (reverse_iterator d = rbegin(); d != rend(); ++d)
+  {
+    /* get the carry for the next iteration */
+    const digit_type rr = *d & 1;
+    /* shift the current digit, add in carry and store */
+    *d = (*d >> 1) | (carry << (valid_bits - 1));
+    /* forward carry to next iteration */
+    carry = rr;
+  }
+  clamp();
+  if (is_zero())
+    sign_ = 1;
+}
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+template<class A, class T>
+typename mp_int<A,T>::digit_type
+mp_int<A,T>::divide_by_3()
+{
+  /* b = 2**valid_bits / 3 */
+  const word_type b = (word_type(1) << static_cast<word_type>(valid_bits)) / word_type(3);
+
+  word_type w = 0;
+  for (reverse_iterator d = rbegin(); d != rend(); ++d)
+  {
+    w = (w << static_cast<word_type>(valid_bits)) | static_cast<word_type>(*d);
+    
+    word_type t;
+    if (w >= 3)
+    {
+      /* multiply w by [1/3] */
+      t = (w * b) >> static_cast<word_type>(valid_bits);
+
+      /* now subtract 3 * [w/3] from w, to get the remainder */
+      w -= t+t+t;
+
+      /* fixup the remainder as required since
+       * the optimization is not exact.
+       */
+      while (w >= 3)
+      {
+        t += 1;
+        w -= 3;
+      }
+    }
+    else
+      t = 0;
+
+    *d = static_cast<digit_type>(t);
+  }  
+
+  // *this is now the quotient
+  // return remainder
+  return static_cast<digit_type>(w);
+}
+
+/* shift right by a certain bit count */
+template<class A, class T>
+void mp_int<A,T>::shift_right(size_type b, mp_int* remainder)
+{
+  if (b == 0)
+  {
+    if (remainder)
+      remainder->zero();
+    return;
+  }
+
+  /* get the remainder */
+  mp_int t;
+  if (remainder)
+  {
+    *remainder = *this;
+    remainder->modulo_2_to_the_power_of(b);
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= static_cast<size_type>(valid_bits))
+    shift_digits_right(b / valid_bits);
+
+  /* shift any bit count < valid_bits */
+  const digit_type D = b % valid_bits;
+  if (D)
+  {
+    const digit_type mask = (digit_type(1) << D) - 1;
+
+    /* shift for lsb */
+    const digit_type shift = valid_bits - D;
+
+    digit_type carry = 0;
+    for (reverse_iterator d = rbegin(); d != rend(); ++d)
+    {
+      /* get the lower bits of this word in a temp */
+      const digit_type rr = *d & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *d = (*d >> D) | (carry << shift);
+
+      /* set the carry to the carry bits of the current word found above */
+      carry = rr;
+    }
+  }
+  clamp();
+  if (is_zero())
+    sign_ = 1;
+}
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+// divide *this by rhs, optionally store remainder
+template<class A, class T>
+void mp_int<A,T>::divide(const mp_int& rhs, mp_int* remainder)
+{
+  if (rhs.is_zero())
+    throw std::domain_error("mp_int::divide: division by zero");
+
+  /* if *this < rhs then q=0, r = *this */
+  if (compare_magnitude(rhs) == -1)
+  {
+    if (remainder)
+      *remainder = *this;
+    zero();
+    return;
+  }
+
+  mp_int q;
+  q.grow_capacity(used_ + 2);
+  q.used_ = used_ + 2;
+  std::memset(q.digits_, 0, q.used_ * sizeof(digit_type));
+
+  mp_int x(*this);
+  mp_int y(rhs);
+
+  /* fix the sign */
+  const int neg = (sign_ == rhs.sign_) ? 1 : -1;
+  x.sign_ = y.sign_ = 1;
+
+  /* normalize both x and y, ensure that y >= beta/2, [beta == 2**valid_bits] */
+  size_type norm = y.precision() % valid_bits;
+  if (norm < valid_bits-1)
+  {
+    norm = valid_bits - 1 - norm;
+    x <<= norm;
+    y <<= norm;
+  }
+  else
+    norm = 0;
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  const size_type n = x.used_ - 1;
+  const size_type t = y.used_ - 1;
+
+  // find leading digit of the quotient
+  /* while (x >= y*beta**(n-t)) do { q[n-t] += 1; x -= y*beta**(n-t) } */
+  y.shift_digits_left(n - t); /* y = y*beta**(n-t) */
+
+  while (x.compare(y) != -1)
+  {
+    ++q[n - t];
+    x -= y;
+  }
+
+  /* reset y by shifting it back down */
+  y.shift_digits_right(n - t);
+
+  // find the remainder of the digits
+  /* step 3. for i from n down to (t + 1) */
+  for (size_type i = n; i >= (t + 1); i--)
+  {
+    if (i > x.used_)
+      continue;
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to beta-1, 
+     * otherwise set q{i-t-1} to (xi*beta + x{i-1})/yt */
+    if (x[i] == y[t])
+      q[i - t - 1] = std::numeric_limits<digit_type>::max();
+    else
+    {
+      word_type tmp = static_cast<word_type>(x[i])
+                   << static_cast<word_type>(valid_bits);
+      tmp |= x[i - 1];
+      tmp /= y[t];
+      q[i - t - 1] = static_cast<digit_type>(tmp);
+    }
+
+    // now fixup quotient estimation
+    /* while (q{i-t-1} * (yt * beta + y{t-1})) > 
+             xi * beta**2 + xi-1 * beta + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+
+    mp_int t1, t2;
+    t1.grow_capacity(3);
+    t2.grow_capacity(3);
+
+    ++q[i - t - 1];
+    do
+    {
+      --q[i - t - 1];
+
+      /* find left hand */
+      t1.zero();
+      t1[0] = (t == 0) ? 0 : y[t - 1];
+      t1[1] = y[t];
+      t1.used_ = 2;
+      t1.multiply_by_digit(q[i - t - 1]);
+
+      /* find right hand */
+      t2[0] = (i < 2) ? 0 : x[i - 2];
+      t2[1] = (i == 0) ? 0 : x[i - 1];
+      t2[2] = x[i];
+      t2.used_ = 3;
+    } while (t1.compare_magnitude(t2) == 1);
+
+    /* step 3.3 x = x - q{i-t-1} * y * beta**{i-t-1} */
+    t1 = y;
+    t1.multiply_by_digit(q[i - t -1]);
+    t1.shift_digits_left(i - t - 1);
+    x -= t1;
+
+    /* if x < 0 then { x = x + y*beta**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign_ == -1)
+    {
+      t1 = y;
+      t1.shift_digits_left(i - t -1);
+      x += t1;
+
+      --q[i - t - 1] = q[i - t - 1];
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign_ = x.is_zero() ? 1 : sign_;
+
+  q.clamp();
+  swap(q);
+  sign_ = neg;
+
+  if (remainder)
+  {
+    x >>= norm;
+    remainder->swap(x);
+  }
+}
+
+/*
+template<class A, class T>
+void divide(const mp_int<A,T>& x, const mp_int<A,T>& y, mp_int<A,T>& q, mp_int<A,T>& r)
+{
+  divide(x, y, &q, &r);
+}
+*/
Added: sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,60 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* Greatest Common Divisor using the binary method */
+template<class A, class T>
+mp_int<A,T> gcd(const mp_int<A,T>& a, const mp_int<A,T>& b)
+{
+  typedef typename mp_int<A,T>::size_type size_type;
+
+  /* either zero then gcd is the largest */
+  if (a.is_zero())
+    return abs(b);
+  if (b.is_zero())
+    return abs(a);
+
+  /* get copies of a and b we can modify */
+  mp_int<A,T> u = abs(a);
+  mp_int<A,T> v = abs(b);
+
+  /* B1.  Find the common power of two for u and v */
+  const size_type u_lsb = u.count_lsb();
+  const size_type v_lsb = v.count_lsb();
+  const size_type     k = std::min(u_lsb, v_lsb);
+
+  if (k > 0)
+  {
+    /* divide the power of two out */
+    u.shift_right(k,0);
+    v.shift_right(k,0);
+  }
+
+  /* divide any remaining factors of two out */
+  if (u_lsb != k)
+    u.shift_right(u_lsb - k, 0);
+
+  if (v_lsb != k)
+    v.shift_right(v_lsb - k, 0);
+
+  while (!v.is_zero())
+  {
+    /* make sure v is the largest */
+    if (u.compare_magnitude(v) == 1)
+      /* swap u and v to make sure v is >= u */
+      u.swap(v);
+     
+    /* subtract smallest from largest */
+    v.sub_smaller_magnitude(u);
+
+    /* Divide out all factors of two */
+    v.shift_right(v.count_lsb(), 0);
+  } 
+
+  /* multiply by 2**k which we divided out at the beginning */
+  u <<= k;
+
+  return u;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,60 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// computes the jacobi c = (a | p) (or Legendre if p is prime)
+// HAC pp. 73 Algorithm 2.149
+template<class A, class T>
+int jacobi(const mp_int<A,T>& a, const mp_int<A,T>& p)
+{
+  typedef typename mp_int<A,T>::digit_type digit_type;
+  typedef typename mp_int<A,T>::size_type  size_type;
+
+  if (p <= digit_type(0))
+    throw std::domain_error("jacobi: p must be greater than 0");
+
+  if (a.is_zero())
+    return 0;
+  
+  if (a == digit_type(1))
+    return 1;
+
+  /* default */
+  int s = 0;
+
+  /* write a = a1 * 2**k  */
+  mp_int<A,T> a1(a);
+
+  // find largest power of two that divides a1
+  const size_type k = a1.count_lsb();
+  // now divide by it
+  a1.shift_right(k,0);
+
+  /* if k is even set s=1 */
+  if ((k & 1) == 0)
+    s = 1;
+  else
+  {
+    // calculate p.digits_[0] mod 8
+    const digit_type residue = p.digits_[0] & 7;
+
+    if (residue == 1 || residue == 7)
+      s = 1;
+    else if (residue == 3 || residue == 5)
+      s = -1;
+  }
+
+  /* if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+  if (((p.digits_[0] & 3) == 3) && ((a1.digits_[0] & 3) == 3))
+    s = -s;
+
+  if (a1 == digit_type(1))
+    return s;
+  else
+  {
+    const mp_int<A,T> p1(p % a1);
+    return s * jacobi(p1, a1);
+  }
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,22 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* computes least common multiple as |a*b|/(a, b) */
+template<class A, class T>
+mp_int<A,T> lcm(const mp_int<A,T>& a, const mp_int<A,T>& b)
+{
+  /* t1 = get the GCD of the two inputs */
+  const mp_int<A,T> t1 = gcd(a,b);
+
+  /* divide the smallest by the GCD */
+  const mp_int<A,T>* smallest = a.compare_magnitude(b) == -1 ? &a : &b;
+
+  mp_int<A,T> t2 = *smallest / t1;
+  
+  t2.sign_ = 1;
+  
+  return t2;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/mod.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/mod.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,209 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* calc a value mod 2**b */
+template<class A, class T>
+void mp_int<A,T>::modulo_2_to_the_power_of(int b)
+{
+  /* if b is <= 0 then zero the int */
+  if (b <= 0)
+  {
+    zero();
+    return;
+  }
+
+  /* if the modulus is larger than the value then return */
+  if (b >= static_cast<int>(used_ * valid_bits))
+    return;
+
+  /* zero digits above the last digit of the modulus */
+  for (size_type x = (b / valid_bits) + ((b % valid_bits) == 0 ? 0 : 1); x < used_; ++x)
+    digits_[x] = 0;
+
+  /* clear the digit that is not completely outside/inside the modulus */
+  digits_[b / valid_bits] &= static_cast<digit_type>(
+      ((digit_type(1)) << ((static_cast<digit_type>(b)) % valid_bits)) - (digit_type(1)));
+
+  clamp();
+  if (is_zero())
+    sign_ = 1;
+}
+
+// hac 14.61, pp608
+// *this = *this**-1 (mod b)
+template<class A, class T>
+void mp_int<A,T>::modinv(const mp_int& b)
+{
+  /* b cannot be negative */
+  if (b.is_negative() || b.is_zero())
+    throw std::domain_error("modinv: b is negative or zero");
+
+  /* if the modulus is odd we can use a faster routine instead */
+  if (b.is_odd())
+    fast_modinv(b);
+  else
+    slow_modinv(b);
+}
+
+/* hac 14.61, pp608 */
+template<class Al, class T>
+void mp_int<Al,T>::slow_modinv(const mp_int& b)
+{
+  /* b cannot be negative */
+  if (b.is_negative() || b.is_zero())
+    throw std::domain_error("mp_int::slow_modinv: b is negative or zero"); // XXX: this is already tested in modinv
+
+  const mp_int x = *this % b;
+  const mp_int y(b); // TODO no need to copy b here since b or y is never changed
+
+  /* [modified] if x,y are both even then return an error! */
+  if (x.is_even() && y.is_even())
+    throw std::domain_error("mp_int::slow_modinv: no inverse exists");// TODO: different text?
+
+  mp_int u(x);
+  mp_int v(y);
+  mp_int A = digit_type(1);
+  mp_int B = digit_type(0);
+  mp_int C = digit_type(0);
+  mp_int D = digit_type(1);
+
+top:
+  while (u.is_even())
+  {
+    u.divide_by_2();
+    
+    if (A.is_odd() || B.is_odd())
+    {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      A += y;
+      B -= x;
+    }
+    A.divide_by_2();
+    B.divide_by_2();
+  }
+
+  while (v.is_even())
+  {
+    v.divide_by_2();
+
+    if (C.is_odd() || D.is_odd())
+    {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      C += y;
+      D -= x;
+    }
+    C.divide_by_2();
+    D.divide_by_2();
+  }
+
+  if (u >= v)
+  {
+    u -= v;
+    A -= C;
+    B -= D;
+  }
+  else
+  {
+    v -= u;
+    C -= A;
+    D -= B;
+  }
+
+  if (!u.is_zero())
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (v != digit_type(1))
+    throw std::domain_error("mp_int::slow_modinv: no inverse exists"); // TODO return false if no inverse exists?
+
+  /* if its too low */
+  while (C.compare_to_digit(0) == -1)
+    C += b;
+  
+  /* too big */
+  while (C.compare_magnitude(b) != -1)
+    C -= b;
+  
+  /* C is now the inverse */
+  swap(C);
+}
+
+/* computes the modular inverse via binary extended euclidean algorithm, 
+ * that is *this = 1 / *this mod b 
+ *
+ * Based on slow modinv except this is optimized for the case where b is 
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+template<class Al, class T>
+void mp_int<Al,T>::fast_modinv(const mp_int& b)
+{
+  if (b.is_even())
+    throw std::domain_error("mp_int::fast_modinv: b must be odd");
+
+  /* x == modulus, y == value to invert */
+  mp_int x = b;
+
+  /* we need y = |a| */
+  mp_int y = *this % b;
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  mp_int u(x);
+  mp_int v(y);
+  mp_int A = digit_type(1);
+  mp_int B = digit_type(0);
+  mp_int C = digit_type(0);
+  mp_int D = digit_type(1);
+
+top:
+  while (u.is_even())
+  {
+    u.divide_by_2();
+    
+    if (B.is_odd())
+      B -= x;
+    
+    B.divide_by_2();
+  }
+
+  while (v.is_even())
+  {
+    v.divide_by_2();
+
+    if (D.is_odd())
+      D -= x;      
+
+    D.divide_by_2();
+  }
+
+  if (u >= v)
+  {
+    /* u = u - v, B = B - D */
+    u -= v;
+    B -=D;
+  }
+  else
+  {
+    v -= u;
+    D -= B;
+  }
+
+  if (!u.is_zero())
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (v != digit_type(1))
+    throw std::domain_error("mp_int::fast_modinv: no inverse exists");
+
+  /* D is now the inverse */
+  while (D.sign_ == -1)
+    D += b;
+
+  swap(D);
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/modular_reduction.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/modular_reduction.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,521 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+template<class A, class T>
+void mp_int<A,T>::reduce_setup(const mp_int& b)
+{
+  pow2(b.used_ * 2 * digit_bits);
+  *this /= b;
+}
+
+// reduces *this mod m, assumes 0 < *this < m**2, mu is 
+// precomputed via reduce_setup.
+// From HAC pp.604 Algorithm 14.42
+template<class A, class T>
+void mp_int<A,T>::reduce(const mp_int& m, const mp_int& mu)
+{
+  const size_type k = m.used_;
+
+  mp_int q(*this);
+
+  /* q1 = x / b**(k-1)  */
+  q.shift_digits_right(k - 1);
+
+  /* according to HAC this optimization is ok */
+  if (k > digit_type(1) << (valid_bits - 1))
+    q *= mu;
+  else
+    q.fast_mul_high_digits(mu, k);
+
+  /* q3 = q2 / b**(k+1) */
+  q.shift_digits_right(k + 1);
+
+  /* x = x mod b**(k+1), quick (no division) */
+  modulo_2_to_the_power_of(valid_bits * (k + 1));
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  q.mul_digits(m, k + 1);
+
+  /* x = x - q */
+  *this -= q;
+
+  /* If x < 0, add b**(k+1) to it */
+  if (is_negative())
+  {
+    q = digit_type(1);
+    q.shift_digits_left(k + 1);
+    *this += q;
+  }
+
+  /* Back off if it's too big */
+  while (compare(m) != -1)
+    sub_smaller_magnitude(m);
+}
+
+/* setups the montgomery reduction stuff */
+template<class A, class T>
+typename mp_int<A,T>::digit_type
+mp_int<A,T>::montgomery_setup() const
+{
+  /* fast inversion mod 2**k
+   *
+   * Based on the fact that
+   *
+   * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+   *                    =>  2*X*A - X*X*A*A = 1
+   *                    =>  2*(1) - (1)     = 1
+   */
+  const digit_type b = digits_[0];
+
+  if (is_even())
+    throw std::domain_error("montgomery_setup: integer must be odd");
+
+  static const size_type S = sizeof(digit_type) * CHAR_BIT;
+
+  digit_type x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+  if (S != 8)
+    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+  if (S == 64 || !(S == 8 || S == 16))
+    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+  if (S == 64)
+    x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+
+  /* rho = -1/m mod b */
+  const digit_type rho = (word_type(1) << (static_cast<word_type>(valid_bits))) - x;
+  return rho;
+}
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+template<class A, class T>
+void mp_int<A,T>::montgomery_reduce(const mp_int& n, digit_type rho)
+{
+  /* can the fast reduction [comba] method be used?
+   *
+   * Note that unlike in mul you're safely allowed *less*
+   * than the available columns [255 per default] since carries
+   * are fixed up in the inner loop.
+   */
+  const size_type digs = n.used_ * 2 + 1;
+/*  const size_type ws = sizeof(word_type) * CHAR_BIT;
+  if (digs < mp_warray && n.used_ < 1 << (ws - (2 * valid_bits)))
+  {
+    fast_montgomery_reduce(n, rho);
+    return;
+  }*/
+  /* grow the input as required */
+  grow_capacity(digs);
+  std::memset(digits_ + used_, 0, (capacity_ - used_) * sizeof(digit_type));
+  used_ = digs;
+
+  for (size_type i = 0; i < n.used_; ++i)
+  {
+    /* mu = ai * rho mod b
+     *
+     * The value of rho must be precalculated via
+     * montgomery_setup() such that
+     * it equals -1/n0 mod b this allows the
+     * following inner loop to reduce the
+     * input one digit at a time
+     */
+    const digit_type mu = static_cast<word_type>(digits_[i]) * rho;
+
+    /* a = a + mu * m * b**i */
+  
+    /* alias for digits of the modulus */
+    digit_type* tmpn = n.digits_;
+
+    /* alias for the digits of x [the input] */
+    digit_type* tmpx = digits_ + i;
+
+    digit_type carry = 0;
+
+    /* Multiply and add in place */
+    for (size_type j = 0; j < n.used_; ++j)
+    {
+      /* compute product and sum */
+      const word_type r = static_cast<word_type>(mu)
+                        * static_cast<word_type>(*tmpn++)
+                        + static_cast<word_type>(carry)
+                        + static_cast<word_type>(*tmpx);
+      
+      carry = r >> digit_bits;
+
+      /* fix digit */
+      *tmpx++ = r;
+    }
+    /* At this point the i'th digit of x should be zero */
+    
+    /* propagate carries upwards as required*/
+    while (carry)
+    {
+      const word_type r = static_cast<word_type>(*tmpx) + carry;
+      *tmpx++ = r;
+      carry = r >> digit_bits;
+    }
+  }
+
+  /* at this point the n.used'th least
+   * significant digits of x are all zero
+   * which means we can shift x to the
+   * right by n.used digits and the
+   * residue is unchanged.
+   */
+
+  /* x = x/b**n.used */
+  clamp();
+  if (is_zero())
+    sign_ = 1;
+  shift_digits_right(n.used_);
+
+  /* if x >= n then x = x - n */
+  if (compare_magnitude(n) != -1)
+    sub_smaller_magnitude(n);
+}
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b. This saves alot of multiple precision shifting.
+ */
+template<class A, class T>
+void mp_int<A,T>::montgomery_calc_normalization(const mp_int& b)
+{
+  /* how many bits of last digit does b use */
+  size_type bits = b.precision() % valid_bits;
+
+  if (b.used_ > 1)
+    pow2((b.used_ - 1) * valid_bits + bits - 1);
+  else
+  {
+    *this = digit_type(1);
+    bits = 1;
+  }
+
+  /* now compute C = A * B mod b */
+  for (int x = bits - 1; x < valid_bits; ++x)
+  {
+    multiply_by_2();
+    if (compare_magnitude(b) != -1)
+      sub_smaller_magnitude(b);
+  }
+}
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+template<class A, class T>
+void mp_int<A,T>::fast_montgomery_reduce(const mp_int& n, digit_type rho)
+{
+  word_type W[mp_warray];
+
+  /* grow a as required */
+  grow_capacity(n.used_ + 1);
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+
+  /* copy the digits of a into W[0..a->used-1] */
+  for (size_type i = 0; i < used_; ++i)
+    W[i] = digits_[i];
+
+  /* zero the high words of W[a->used..m->used*2] */
+  std::memset(W + used_, 0, (n.used_ * 2 + 1) * sizeof(word_type));
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (size_type i = 0; i < n.used_; ++i)
+  {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    const digit_type mu = ((W[i] & mp_mask) * rho) & mp_mask;
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop. The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    /* inner loop */
+    for (size_type j = 0; j < n.used_; ++j)
+      W[i+j] += static_cast<word_type>(mu) * static_cast<word_type>(n.digits_[j]);
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[i + 1] += W[i] >> static_cast<word_type>(valid_bits);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+
+  /* now fix rest of carries */
+
+  for (size_type i = n.used_ + 1; i <= n.used_ * 2 + 1; ++i)
+    W[i] += W[i-1] >> static_cast<word_type>(valid_bits);
+
+  /* copy out, A = A/b**n
+   *
+   * The result is A/b**n but instead of converting from an
+   * array of mp_word to mp_digit than calling mp_rshd
+   * we just copy them in the right order
+   */
+
+  for (size_type i = 0; i < n.used_ + 1; ++i)
+    digits_[i] = W[n.used_ + i] & static_cast<word_type>(mp_mask);
+
+  /* set the max used and clamp */
+  used_ = n.used_ + 1;
+  clamp();
+  if (is_zero())
+    sign_ = 1;
+
+  /* if A >= m then A = A - m */
+  if (compare_magnitude(n) != -1)
+    sub_smaller_magnitude(n);
+}
+
+/* determines the setup value */
+template<class A, class T>
+typename mp_int<A,T>::digit_type
+mp_int<A,T>::dr_setup() const
+{
+   /* the casts are required if valid_bits is one less than
+    * the number of bits in a valid_bits [e.g. valid_bits==31]
+    */
+   const digit_type d = (word_type(1) << static_cast<word_type>(valid_bits))
+                      - static_cast<word_type>(digits_[0]);
+   return d;
+}
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ *                 Chae Hoon Lim, Pil Joong Lee,
+ *          POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input *this must be in the range 0 <= *this <= (n-1)**2
+ */
+template<class A, class T>
+void mp_int<A,T>::dr_reduce(const mp_int& n, digit_type k)
+{
+  /* m = digits in modulus */
+  const size_type m = n.used_;
+
+  /* ensure that *this has at least 2m digits */
+  grow_capacity(m + m);
+  std::memset(digits_ + used_, 0, (m + m - used_) * sizeof(digit_type));
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+  /* set carry to zero */
+  digit_type mu = 0;
+
+  /* compute (*this mod B**m) + k * [*this/B**m] inline and inplace */
+  for (size_type i = 0; i < m; ++i)
+  {
+    const word_type r = static_cast<word_type>(digits_[m+i])
+                      * static_cast<word_type>(k) + digits_[i] + mu;
+    digits_[i] = static_cast<digit_type>(r);
+    mu = static_cast<digit_type>(r >> static_cast<word_type>(digit_bits));
+  }
+
+  /* set final carry */
+  digits_[m] = mu;
+
+  /* zero words above m */
+  if (used_ > m + 1) // guard against overflow
+    std::memset(digits_ + m + 1, 0, (used_ - (m + 1)) * sizeof(digit_type));
+
+  /* clamp, sub and return */
+  clamp();
+  if (is_zero())
+    sign_ = 1;
+
+  /* if *this >= n then subtract and reduce again
+   * Each successive "recursion" makes the input smaller and smaller.
+   */
+  if (compare_magnitude(n) != -1)
+  {
+    sub_smaller_magnitude(n);
+    goto top;
+  }
+}
+
+/* determines if a number is a valid DR modulus */
+template<class A, class T>
+bool mp_int<A,T>::is_dr_modulus() const
+{
+  /* must be at least two digits */
+  if (used_ < 2)
+    return false;
+
+  /* must be of the form b**k - a [a <= b] so all
+   * but the first digit must be equal to -1 (mod b).
+   */
+  for (size_type i = 1; i < used_; ++i)
+  {
+    if (digits_[i] != digit_max)
+      return false;
+  }
+  return true;
+}
+
+/* determines the setup value */
+template<class A, class T>
+typename mp_int<A,T>::digit_type
+mp_int<A,T>::reduce_2k_setup() const
+{
+  mp_int tmp;
+  const size_type p = precision();
+
+  tmp.pow2(p);
+  tmp.sub_smaller_magnitude(*this);
+
+  return tmp.digits_[0];
+}
+
+/* reduces *this modulo n where n is of the form 2**p - d */
+template<class A, class T>
+void mp_int<A,T>::reduce_2k(const mp_int& n, digit_type d)
+{
+  const size_type p = n.precision();
+
+top:
+
+  mp_int q(*this);
+  
+  /* q = a/2**p, a = a mod 2**p */
+  q.shift_right(p, this);
+
+  if (d != 1)
+    /* q = q * d */
+    q.multiply_by_digit(d);
+  /* a = a + q */
+  add_magnitude(q);
+
+  if (compare_magnitude(n) != -1)
+  {
+    sub_smaller_magnitude(n);
+    goto top;
+  }
+}
+
+/* determines if mp_reduce_2k can be used */
+template<class A, class T>
+bool mp_int<A,T>::reduce_is_2k() const
+{
+  if (used_ == 1)
+    return true;
+  else if (used_ > 1)
+  {
+    const size_type bits = precision();
+    size_type j = 1;
+    digit_type k = 1;
+    
+    /* Test every bit from the second digit up, must be 1 */
+    for (size_type i = valid_bits; i < bits; ++i)
+    {
+      if ((digits_[j] & k) == 0)
+        return false;
+      k <<= 1;
+      if (k > mp_mask) // FIXME this can never happen with the new code
+      {
+        ++j;
+        k = 1;
+      }
+    }
+  }
+  return true;
+}
+
+/* determines the setup value */
+template<class A, class T>
+mp_int<A,T> mp_int<A,T>::reduce_2k_l_setup()
+{
+  mp_int tmp;
+
+  tmp.pow2(precision());
+  return tmp - *this;
+}
+
+/* reduces *this modulo n where n is of the form 2**p - d 
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+template<class A, class T>
+void mp_int<A,T>::reduce_2k_l(const mp_int& n, const mp_int& d)
+{
+  const size_type p = n.precision();
+
+top:
+
+  mp_int q(*this);
+
+  /* q = a/2**p, a = a mod 2**p */
+  q.shift_right(p, this);
+
+  /* q = q * d */
+  q *= d;
+
+  /* a = a + q */
+  add_magnitude(q);
+
+  if (compare_magnitude(n) != -1)
+  {
+    sub_smaller_magnitude(n);
+    goto top;
+  }
+}
+
+/* determines if reduce_2k_l can be used */
+template<class A, class T>
+bool mp_int<A,T>::reduce_is_2k_l() const
+{
+  if (used_ == 1)
+    return true;
+  else if (used_ > 1)
+  {
+    size_type count = 0;
+    // if more than half of the digits are -1 we're sold
+    for (size_type i = 0; i < used_; ++i)
+      if (digits_[i] == digit_max)
+        ++count;
+    return count >= used_ / 2 ? true : false;
+  }
+  return false;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,893 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_MP_INT_HPP
+#define BOOST_MP_MATH_MP_INT_MP_INT_HPP
+
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <iosfwd>
+#include <iterator> // reverse_iterator
+#include <limits>
+#include <stdexcept>
+#include <sstream>
+#include <string>
+
+#include <boost/config.hpp>
+#include <boost/random.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/serialization/string.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/mp_math/mp_int/traits.hpp>
+#include <boost/mp_math/mp_int/detail/string_conversion_constants.hpp>
+#include <boost/mp_math/mp_int/detail/integral_ops.hpp>
+#include <boost/mp_math/mp_int/detail/meta_math.hpp>
+#include <boost/mp_math/mp_int/detail/prime_tab.hpp>
+#include <boost/mp_math/mp_int/detail/primitive_ops.hpp>
+
+
+namespace boost {
+namespace mp_math {
+
+
+// digits are stored in least significant order
+
+template<
+  class Allocator = std::allocator<void>,
+  class Traits = mp_int_traits<>
+>
+struct mp_int
+:
+  Allocator::template rebind<typename Traits::digit_type>::other
+{
+  typedef Allocator                       allocator_type;
+  typedef Traits                          traits_type;
+  typedef typename traits_type::size_type size_type;
+
+  mp_int();
+
+  template<typename IntegralT>
+  mp_int(IntegralT, typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
+
+  mp_int(const char*);
+  mp_int(const char*, std::ios_base::fmtflags);
+
+  #ifndef BOOST_NO_CWCHAR
+  mp_int(const wchar_t*);
+  mp_int(const wchar_t*, std::ios_base::fmtflags);
+  #endif
+
+  template<typename charT, class traits, class Alloc>
+  mp_int(const std::basic_string<charT,traits,Alloc>&);
+  
+  template<typename charT, class traits, class Alloc>
+  mp_int(const std::basic_string<charT,traits,Alloc>&, std::ios_base::fmtflags);
+  
+  template<typename RandomAccessIterator>
+  mp_int(RandomAccessIterator first, RandomAccessIterator last);
+  
+  template<typename RandomAccessIterator>
+  mp_int(RandomAccessIterator first, RandomAccessIterator last,
+         std::ios_base::fmtflags f);
+
+  mp_int(const mp_int& copy);
+
+  #ifdef BOOST_HAS_RVALUE_REFS
+  mp_int(mp_int&& copy);
+  #endif
+  
+  ~mp_int();
+
+  mp_int& operator = (const mp_int& rhs);
+
+  #ifdef BOOST_HAS_RVALUE_REFS
+  mp_int& operator = (mp_int&& rhs);
+  #endif
+  
+  template<typename IntegralT>
+  mp_int& operator = (IntegralT rhs);
+
+  mp_int& operator = (const char*);
+  
+  #ifndef BOOST_NO_CWCHAR
+  mp_int& operator = (const wchar_t*);
+  #endif
+
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator = (const std::basic_string<charT,traits,Alloc>&);
+
+  void assign(const char*, std::ios_base::fmtflags);
+
+  #ifndef BOOST_NO_CWCHAR
+  void assign(const wchar_t*, std::ios_base::fmtflags);
+  #endif
+
+  template<typename charT, class traits, class Alloc>
+  void assign(const std::basic_string<charT,traits,Alloc>&,
+              std::ios_base::fmtflags);  
+  
+  template<typename RandomAccessIterator>
+  void assign(RandomAccessIterator first, RandomAccessIterator last,
+              std::ios_base::fmtflags);
+
+  #ifdef BOOST_HAS_RVALUE_REFS
+  void swap(mp_int&& other);
+  #else
+  void swap(mp_int& other);
+  #endif
+
+  mp_int& operator ++();
+  mp_int& operator --();
+  mp_int  operator ++(int);
+  mp_int  operator --(int);
+  mp_int& operator <<= (size_type);
+  mp_int& operator >>= (size_type);
+  mp_int& operator - ();
+
+  mp_int& operator += (const mp_int&);
+  mp_int& operator -= (const mp_int&);
+  mp_int& operator *= (const mp_int&);
+  mp_int& operator /= (const mp_int&);
+  mp_int& operator %= (const mp_int&);
+  mp_int& operator |= (const mp_int&);
+  mp_int& operator &= (const mp_int&);
+  mp_int& operator ^= (const mp_int&);
+
+  template<typename IntegralT> mp_int& operator += (IntegralT);
+  template<typename IntegralT> mp_int& operator -= (IntegralT);
+  template<typename IntegralT> mp_int& operator *= (IntegralT);
+  template<typename IntegralT> mp_int& operator /= (IntegralT);
+  template<typename IntegralT> mp_int& operator %= (IntegralT);
+  template<typename IntegralT> mp_int& operator |= (IntegralT);
+  template<typename IntegralT> mp_int& operator &= (IntegralT);
+  template<typename IntegralT> mp_int& operator ^= (IntegralT);
+
+  mp_int& operator += (const char*);
+  mp_int& operator -= (const char*);
+  mp_int& operator *= (const char*);
+  mp_int& operator /= (const char*);
+  mp_int& operator %= (const char*);
+  mp_int& operator |= (const char*);
+  mp_int& operator &= (const char*);
+  mp_int& operator ^= (const char*);
+
+  #ifndef BOOST_NO_CWCHAR
+  mp_int& operator += (const wchar_t*);
+  mp_int& operator -= (const wchar_t*);
+  mp_int& operator *= (const wchar_t*);
+  mp_int& operator /= (const wchar_t*);
+  mp_int& operator %= (const wchar_t*);
+  mp_int& operator |= (const wchar_t*);
+  mp_int& operator &= (const wchar_t*);
+  mp_int& operator ^= (const wchar_t*);
+  #endif
+
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator += (const std::basic_string<charT,traits,Alloc>&);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator -= (const std::basic_string<charT,traits,Alloc>&);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator *= (const std::basic_string<charT,traits,Alloc>&);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator /= (const std::basic_string<charT,traits,Alloc>&);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator %= (const std::basic_string<charT,traits,Alloc>&);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator |= (const std::basic_string<charT,traits,Alloc>&);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator &= (const std::basic_string<charT,traits,Alloc>&);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator ^= (const std::basic_string<charT,traits,Alloc>&);
+
+  allocator_type get_allocator() const { return allocator_type(); }
+
+private:
+
+  typedef int mp_int::*unspecified_bool_type;
+
+public:
+
+  operator unspecified_bool_type() const
+  {
+	  return is_zero() ? 0 : &mp_int::sign_;
+  }
+
+  bool is_even() const { return (digits_[0] & digit_type(1)) == 0; }
+  bool is_odd () const { return (digits_[0] & digit_type(1)) == 1; }
+
+  bool is_positive() const { return sign_ ==  1; }
+  bool is_negative() const { return sign_ == -1; }
+
+  template<class StringT>
+  StringT to_string(std::ios_base::fmtflags f = std::ios_base::dec) const;
+
+  template<typename IntegralT>
+  IntegralT to_integral() const;
+
+public: // low level interface
+
+  typedef typename traits_type::digit_type        digit_type;
+  typedef typename traits_type::word_type         word_type;
+  typedef typename traits_type::digit_type*       iterator;
+  typedef const typename traits_type::digit_type* const_iterator;
+  typedef std::reverse_iterator<iterator>         reverse_iterator;
+  typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
+  typedef detail::primitive_ops<digit_type, word_type, size_type> ops_type;
+
+  // bits per digit, we subtract one because we count from 0
+  static const int valid_bits = std::numeric_limits<digit_type>::digits;
+  static const int digit_bits = std::numeric_limits<digit_type>::digits;
+  // used to mask off the most significant bit(s)
+  static const digit_type mp_mask = (word_type(1) << valid_bits) - 1;
+  static const size_type mp_warray = 512;
+    //1 << (std::numeric_limits<word_type>::digits - 2 * valid_bits + 1);
+  static const digit_type digit_max = static_cast<digit_type>(-1);
+
+  template<typename RandomAccessIterator>
+  void init(RandomAccessIterator first, RandomAccessIterator last);
+
+  template<typename RandomAccessIterator>
+  void init(RandomAccessIterator first, RandomAccessIterator last,
+            std::ios_base::fmtflags f);
+
+  iterator       begin()       { return digits_;         }
+  iterator       end  ()       { return digits_ + used_; }
+  const_iterator begin() const { return digits_;         }
+  const_iterator end  () const { return digits_ + used_; }
+  reverse_iterator       rbegin()       { return reverse_iterator(end());   }
+  reverse_iterator       rend  ()       { return reverse_iterator(begin()); }
+  const_reverse_iterator rbegin() const { return const_reverse_iterator(end());   }
+  const_reverse_iterator rend  () const { return const_reverse_iterator(begin()); }
+
+  digit_type&       operator[](size_type i)       { return digits_[i]; }
+  const digit_type& operator[](size_type i) const { return digits_[i]; }
+  
+  digit_type&       at(size_type i)
+  {
+    if (i >= used_)
+      throw std::out_of_range("mp_int::at: array subscript out of range");
+    return digits_[i];
+  }
+  const digit_type& at(size_type i) const
+  {
+    if (i >= used_)
+      throw std::out_of_range("mp_int::at: array subscript out of range");
+    return digits_[i];
+  }
+
+  void zero();
+
+  // debug functionality
+  void print(bool all=false) const;
+  bool test_invariants() const;
+
+  size_type size() const { return used_; }
+  size_type capacity() const { return capacity_; }
+
+  void set_size(size_type s) { used_ = s; }
+
+  int sign() const { return sign_; }
+  void set_sign(int s) { sign_ = s; }
+
+  digit_type* digits() { return digits_; }
+  const digit_type* digits() const { return digits_; }
+
+  void grow_capacity(size_type n);
+  void clamp();
+
+  int compare_magnitude(const mp_int& rhs) const;
+  int compare_to_digit(digit_type) const;
+  int compare(const mp_int& rhs) const;
+
+  void add_magnitude(const mp_int& rhs);
+  void sub_smaller_magnitude(const mp_int& rhs);
+
+  bool is_zero() const;
+  bool is_power_of_two() const;
+  void add_digit(digit_type);
+  void sub_digit(digit_type);
+
+  void shift_digits_left(size_type);
+  void shift_digits_right(size_type);
+
+  void multiply_by_digit(digit_type);
+  void karatsuba_mul(const mp_int&);
+  void toom_cook_mul(const mp_int&);
+  void multiply_by_2();
+  void mul_digits(const mp_int&, size_type num_digits);
+  void mul_high_digits(const mp_int&, size_type num_digits);
+  void fast_mul_digits(const mp_int&, size_type num_digits);
+  void fast_mul_high_digits(const mp_int&, size_type num_digits);
+
+  void sqr();
+  void toom_sqr();
+  void karatsuba_sqr();
+  void comba_sqr();
+
+  digit_type divide_by_digit(digit_type); // returns remainder
+  void divide(const mp_int& divisor, mp_int* remainder);
+  void divide_by_2();
+  digit_type divide_by_3();
+  void modulo_2_to_the_power_of(int);
+  size_type precision() const;
+  size_type count_lsb() const;
+  void shift_right(size_type b, mp_int* remainder);
+  
+  void reduce_setup(const mp_int&);
+  void reduce(const mp_int& m, const mp_int& mu);
+  
+  digit_type montgomery_setup() const;
+  void montgomery_reduce(const mp_int& n, digit_type rho);
+  void montgomery_calc_normalization(const mp_int&);
+  void fast_montgomery_reduce(const mp_int& n, digit_type rho);
+  
+  void dr_reduce(const mp_int& n, digit_type k);
+  digit_type dr_setup() const;
+  bool is_dr_modulus() const;
+  
+  digit_type reduce_2k_setup() const;
+  void reduce_2k(const mp_int& n, digit_type d);
+  bool reduce_is_2k() const;
+
+  mp_int reduce_2k_l_setup();
+  void reduce_2k_l(const mp_int& n, const mp_int& d);
+  bool reduce_is_2k_l() const;
+  
+  void pow2(size_type b);
+  void pow(digit_type);
+
+  void modpow(const mp_int& exp, const mp_int& m);
+  void barret_modpow(const mp_int& exp, const mp_int& m, int reduction_mode);
+  void fast_modpow(const mp_int& exp, const mp_int& m, int reduction_mode);
+
+  void modinv(const mp_int& b);
+  void slow_modinv(const mp_int& b);
+  void fast_modinv(const mp_int& b);
+
+  void set_least_significant_bit()
+  {
+    digits_[0] |= digit_type(1);
+  }
+  
+  void set_bit(size_type bit)
+  {
+    digits_[bit / valid_bits] |=
+      digit_type(1) << digit_type(bit % valid_bits);
+  }
+
+  template<class A, class T>
+  friend bool operator == (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  friend bool operator < (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  friend mp_int<A,T> abs(const mp_int<A,T>& x);
+  template<class A, class T>
+  friend mp_int<A,T> gcd(const mp_int<A,T>& a, const mp_int<A,T>& b);
+  template<class A, class T>
+  friend int jacobi(const mp_int<A,T>& a, const mp_int<A,T>& b);
+
+  template<typename Iter>
+  void from_string(Iter first, Iter last, unsigned radix);
+
+private:
+  
+  friend class boost::serialization::access;
+  template<class Archive>
+  void save(Archive & ar, const unsigned int /*version*/) const
+  {
+    const std::string s = to_string<std::string>(std::ios_base::hex);
+    ar & s;
+  }
+  template<class Archive>
+  void load(Archive & ar, const unsigned int /*version*/)
+  {
+    std::string s;
+    ar & s;
+    assign(s, std::ios_base::hex);
+  }
+  BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+  digit_type* digits_;
+  size_type used_, capacity_;
+  int sign_;
+};
+
+
+
+template<class A, class T>
+void mp_int<A,T>::print(bool all) const
+{
+  using std::cout;
+  if (is_negative())
+  cout << '-';
+  cout << used_ << "{";
+  for (size_type i = 0; i < used_; ++i)
+  {
+    cout << static_cast<word_type>(digits_[i]);
+    if (i < used_  - 1)
+      cout << ",";
+  }
+  cout << "}";
+  
+  if (all)
+  {
+    cout << capacity_ - used_ << "{";
+    for (size_type i = used_; i < capacity_; ++i)
+    {
+      cout << static_cast<word_type>(digits_[i]);
+      if (i < capacity_  - 1)
+        cout << ",";
+    }
+    cout << "}";
+  }
+  cout << "\n";
+}
+
+template<class A, class T>
+bool mp_int<A,T>::test_invariants() const
+{
+  if (used_) // don't test uninitialized mp_ints
+  {
+    if (used_ > capacity_)
+      return false;
+    if (digits_[used_-1] == 0)
+      return false;
+    if (sign_ != 1 && sign_ != -1)
+      return false;
+    if (is_zero() && sign_ != 1)
+      return false;
+  }
+  return true;
+}
+
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator = (const mp_int<A,T>& rhs)
+{
+  if (this != &rhs)
+  {
+    if ((capacity_ == 0) || (capacity_ < rhs.capacity_))
+      mp_int(rhs).swap(*this);
+    else
+    {
+      std::memcpy(digits_, rhs.digits_, rhs.used_ * sizeof(digit_type));
+      used_ = rhs.used_;
+      sign_ = rhs.sign_;
+    }
+  }
+  return *this;
+}
+
+#ifdef BOOST_HAS_RVALUE_REFS
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator = (mp_int<A,T>&& rhs)
+{
+  if (this != &rhs)
+  {
+    this->deallocate(digits_, capacity_);
+    digits_ = 0;
+    used_ = 0;
+    capacity_ = 0;
+    sign_ = 1;
+    swap(rhs);
+  }
+  return *this;
+}
+#endif
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator = (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::assign(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator = (const char* s)
+{
+  used_ = 0;
+  init(s, s + std::strlen(s));
+  return *this;
+}
+
+#ifndef BOOST_NO_CWCHAR
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator = (const wchar_t* s)
+{
+  used_ = 0;
+  init(s, s + std::wcslen(s));
+  return *this;
+}
+#endif
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+mp_int<A,T>& mp_int<A,T>::operator = (const std::basic_string<charT,traits,Alloc>& s)
+{
+  used_ = 0;
+  init(s.begin(), s.end());
+  return *this;
+}
+
+template<class A, class T>
+inline void
+mp_int<A,T>::assign(const char* s, std::ios_base::fmtflags f)
+{
+  assign(s, s + std::strlen(s), f);
+}
+
+#ifndef BOOST_NO_CWCHAR
+template<class A, class T>
+inline void
+mp_int<A,T>::assign(const wchar_t* s, std::ios_base::fmtflags f)
+{
+  assign(s, s + std::wcslen(s), f);
+}
+#endif
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline void
+mp_int<A,T>::assign(const std::basic_string<charT,traits,Alloc>& s,
+                    std::ios_base::fmtflags f)
+{
+  assign(s.begin(), s.end(), f);
+}
+
+template<class A, class T>
+template<typename RandomAccessIterator>
+inline void
+mp_int<A,T>::assign(RandomAccessIterator first, RandomAccessIterator last,
+                    std::ios_base::fmtflags f)
+{
+  used_ = 0;
+  init(first, last, f);
+}
+
+
+template<class A, class T>
+#ifdef BOOST_HAS_RVALUE_REFS
+void mp_int<A,T>::swap(mp_int&& other)
+#else
+void mp_int<A,T>::swap(mp_int& other)
+#endif
+{
+  std::swap(digits_, other.digits_);
+  std::swap(used_, other.used_);
+  std::swap(capacity_, other.capacity_);
+  std::swap(sign_, other.sign_);
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator += (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::add(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator -= (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::subtract(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator *= (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::multiply(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator /= (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::divide(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator %= (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::modulo(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator |= (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::bitwise_or(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator &= (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::bitwise_and(*this, rhs);
+  return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline mp_int<A,T>& mp_int<A,T>::operator ^= (IntegralT rhs)
+{
+  detail::integral_ops<IntegralT>::bitwise_xor(*this, rhs);
+  return *this;
+}
+
+
+template<class A, class T>
+void mp_int<A,T>::zero()
+{
+  grow_capacity(1);
+  digits_[0] = 0;
+  used_ = 1;
+  sign_ = 1;
+}
+
+template<class A, class T>
+void mp_int<A,T>::grow_capacity(size_type n)
+{
+  if (capacity_ < n)
+  {
+    const size_type new_cap = capacity_ + capacity_;
+    if (new_cap > n)
+      n = new_cap;
+    digit_type* d = this->allocate(n, digits_);
+    std::memcpy(d, digits_, sizeof(digit_type) * used_);
+    this->deallocate(digits_, capacity_);
+    digits_ = d;
+    capacity_ = n;
+  }
+}
+
+/* trim unused digits 
+ *
+ * This is used to ensure that leading zero digits are trimmed.
+ * Typically very fast.
+ */
+template<class A, class T>
+void mp_int<A,T>::clamp()
+{
+  /* decrease used while the most significant digit is zero. */
+  while (used_ > 1 && digits_[used_-1] == 0)
+    --used_;
+}
+
+template<class A, class T>
+inline bool mp_int<A,T>::is_zero() const
+{
+  return used_ == 1 && digits_[0] == 0;
+}
+
+// disregards the sign of the numbers
+// return 1 if *this is greater
+// returns 0 if both are equal
+// return -1 if *this is smaller
+template<class A, class T>
+int mp_int<A,T>::compare_magnitude(const mp_int& rhs) const
+{
+  /* compare based on # of non-zero digits */
+  if (used_ > rhs.used_)
+    return 1;
+  
+  if (used_ < rhs.used_)
+    return -1;
+
+  /* compare based on digits  */
+  const_reverse_iterator d = rbegin();
+  const_reverse_iterator d2 = rhs.rbegin();
+  for (; d != rend(); ++d, ++d2)
+  {
+    if (*d > *d2)
+      return 1;
+    if (*d < *d2)
+      return -1;
+  }
+  return 0;
+}
+
+template<class A, class T>
+int mp_int<A,T>::compare_to_digit(digit_type d) const
+{
+  /* compare based on sign */
+  if (is_negative())
+    return -1;
+
+  /* compare based on magnitude */
+  if (used_ > 1)
+    return 1;
+
+  /* compare the only digit of *this to d */
+  if (digits_[0] > d)
+    return 1;
+  else if (digits_[0] < d)
+    return -1;
+  else
+    return 0;
+}
+
+template<class A, class T>
+int mp_int<A,T>::compare(const mp_int& rhs) const
+{
+  /* compare based on sign */
+  if (sign_ != rhs.sign_)
+  {
+    if (is_negative())
+      return -1;
+    else
+      return 1;
+  }
+  
+  /* compare digits */
+  if (is_negative())
+    /* if negative compare opposite direction */
+    return rhs.compare_magnitude(*this);
+  else
+    return compare_magnitude(rhs);
+}
+
+// {A,B,C,D,E} shifted left by 2 digits becomes
+// {0,0,A,B,C,D,E}
+template<class A, class T>
+void mp_int<A,T>::shift_digits_left(size_type b)
+{
+  if (b <= 0)
+    return;
+
+  grow_capacity(used_ + b);
+
+  std::memmove(digits_ + b, digits_, used_ * sizeof(digit_type));
+
+  // zero the lower digits
+  std::memset(digits_, 0, b * sizeof(digit_type));
+
+  used_ += b;
+}
+
+// {A,B,C,D,E} shifted right by 2 digits becomes
+// {C,D,E}
+template<class A, class T>
+void mp_int<A,T>::shift_digits_right(size_type b)
+{
+  if (b <= 0)
+    return;
+
+  if (used_ <= b)
+  {
+    zero();
+    return;
+  }
+
+  /* shift the digits down */
+  std::memmove(digits_, digits_ + b, (used_ - b) * sizeof(digit_type));
+
+  /* zero the top digits */
+  std::memset(digits_ + used_ - b, 0, b * sizeof(digit_type));
+  
+  /* remove excess digits */
+  used_ -= b;
+}
+
+template<class A, class T>
+typename mp_int<A,T>::size_type
+mp_int<A,T>::precision() const
+{
+  /* get number of digits and add that */
+  size_type r = (used_ - 1) * valid_bits;
+  
+  /* take the last digit and count the bits in it */
+  digit_type q = digits_[used_ - 1];
+  while (q > 0U)
+  {
+    ++r;
+    q >>= 1;
+  }
+  return r;
+}
+
+/* Counts the number of lsbs which are zero before the first one bit */
+template<class A, class T>
+typename mp_int<A,T>::size_type
+mp_int<A,T>::count_lsb() const
+{
+  static const size_type lnz[16] = {
+    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+  };
+
+  /* easy out */
+  if (is_zero())
+    return 0;
+
+  /* scan lower digits until non-zero */
+  size_type x = 0;
+  while (x < used_ && digits_[x] == 0)
+    ++x;
+  digit_type q = digits_[x];
+  x *= valid_bits;
+
+  /* now scan this digit until a 1 is found */
+  if ((q & 1) == 0)
+  {
+    digit_type qq;
+    do
+    {
+      qq  = q & 15;
+      x  += lnz[qq];
+      q >>= 4;
+    } while (qq == 0);
+  }
+  return x;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline IntegralT mp_int<A,T>::to_integral() const
+{
+  return detail::integral_ops<IntegralT>::convert(*this);
+}
+
+
+template<class A, class T>
+inline void swap(mp_int<A,T>& lhs, mp_int<A,T>& rhs)
+{
+  lhs.swap(rhs);
+}
+
+#ifdef BOOST_HAS_RVALUE_REFS
+template<class A, class T>
+inline void swap(mp_int<A,T>&& lhs, mp_int<A,T>& rhs)
+{
+  lhs.swap(rhs);
+}
+template<class A, class T>
+inline void swap(mp_int<A,T>& lhs, mp_int<A,T>&& rhs)
+{
+  lhs.swap(rhs);
+}
+#endif
+
+
+
+
+
+
+#include <boost/mp_math/mp_int/abs.hpp>
+#include <boost/mp_math/mp_int/add.hpp>
+#include <boost/mp_math/mp_int/ctors.hpp>
+#include <boost/mp_math/mp_int/div.hpp>
+#include <boost/mp_math/mp_int/gcd.hpp>
+#include <boost/mp_math/mp_int/jacobi.hpp>
+#include <boost/mp_math/mp_int/lcm.hpp>
+#include <boost/mp_math/mp_int/mod.hpp>
+#include <boost/mp_math/mp_int/modular_reduction.hpp>
+#include <boost/mp_math/mp_int/mul.hpp>
+#include <boost/mp_math/mp_int/operators.hpp>
+#include <boost/mp_math/mp_int/pow.hpp>
+#include <boost/mp_math/mp_int/random.hpp>
+#include <boost/mp_math/mp_int/prime.hpp>
+#include <boost/mp_math/mp_int/root.hpp>
+#include <boost/mp_math/mp_int/sqr.hpp>
+#include <boost/mp_math/mp_int/sub.hpp>
+#include <boost/mp_math/mp_int/string_conversion.hpp>
+
+} // namespace mp_math
+} // namespace boost
+
+#include <boost/mp_math/mp_int/numeric_limits.hpp>
+
+
+#endif
Added: sandbox/mp_math/boost/mp_math/mp_int/mul.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/mul.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,375 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// multiplies by a single digit
+template<class A, class T>
+void mp_int<A,T>::multiply_by_digit(digit_type x)
+{
+  if (x == 0)
+  {
+    zero();
+    return;
+  }
+  else if (x == 1)
+    return;
+
+  // make sure we can hold the result
+  grow_capacity(used_ + 1);
+  
+  const digit_type carry = ops_type::multiply_by_digit(digits_, digits_, used_, x);
+
+  if (carry)
+    digits_[used_++] = carry;
+}
+
+/* *this *= 2 */
+template<class A, class T>
+void mp_int<A,T>::multiply_by_2()
+{
+  grow_capacity(used_ + 1);
+
+  digit_type carry = 0;
+  for (size_type x = 0; x < used_; ++x)
+  {
+    /* get what will be the *next* carry bit from the 
+     * MSB of the current digit 
+     */
+    const digit_type rr = digits_[x] >> static_cast<digit_type>(valid_bits - 1);
+    
+    /* now shift up this digit, add in the carry [from the previous] */
+    digits_[x] = (digits_[x] << digit_type(1)) | carry;
+ 
+    /* copy the carry that would be from the source 
+     * digit into the next iteration 
+     */
+    carry = rr;
+  }
+
+  /* new leading digit? */
+  if (carry)
+  {
+    /* add a MSB which is always 1 at this point */
+    digits_[used_] = 1;
+    ++used_;
+  }
+}
+
+
+// multiplication using the Toom-Cook 3-way algorithm 
+//
+// Much more complicated than Karatsuba but has a lower 
+// asymptotic running time of O(N**1.464). This algorithm is 
+// only particularly useful on VERY large inputs 
+// (we're talking 1000s of digits here...).
+template<class A, class T>
+void mp_int<A,T>::toom_cook_mul(const mp_int& b)
+{
+  const size_type B = std::min(used_, b.used_) / 3;
+  
+  // a = a2 * B**2 + a1 * B + a0
+  mp_int a0(*this);
+  a0.modulo_2_to_the_power_of(valid_bits * B);
+  mp_int a1(*this);
+  a1.shift_digits_right(B);
+  a1.modulo_2_to_the_power_of(valid_bits * B);
+  mp_int a2(*this);
+  a2.shift_digits_right(B*2);
+  
+  // b = b2 * B**2 + b1 * B + b0
+  mp_int b0(b);
+  b0.modulo_2_to_the_power_of(valid_bits * B);
+  mp_int b1(b);
+  b1.shift_digits_right(B);
+  b1.modulo_2_to_the_power_of(valid_bits * B);
+  mp_int b2(b);
+  b2.shift_digits_right(B*2);
+
+  // w0 = a0*b0
+  const mp_int w0(a0 * b0);
+  
+  // w4 = a2 * b2
+  mp_int w4 = a2 * b2;
+  
+  // w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0))
+  mp_int tmp1 = a0;
+  tmp1.multiply_by_2();
+  tmp1 += a1;
+  tmp1.multiply_by_2();
+  tmp1 += a2;
+  
+  mp_int tmp2 = b0;
+  tmp2.multiply_by_2();
+  tmp2 += b1;
+  tmp2.multiply_by_2();
+  tmp2 += b2;
+
+  mp_int w1 = tmp1 * tmp2;
+
+  // w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2))
+  tmp1 = a2;
+  tmp1.multiply_by_2();
+  tmp1 += a1;
+  tmp1.multiply_by_2();
+  tmp1 += a0;
+
+  tmp2 = b2;
+  tmp2.multiply_by_2();
+  tmp2 += b1;
+  tmp2.multiply_by_2();
+  tmp2 += b0;
+
+  mp_int w3 = tmp1 * tmp2;
+
+  // w2 = (a2 + a1 + a0)(b2 + b1 + b0)
+  tmp1 = a2 + a1;
+  tmp1 += a0;
+  tmp2 = b2 + b1;
+  tmp2 += b0;
+  mp_int w2 = tmp1 * tmp2;
+
+  // now solve the matrix 
+  //
+  // 0  0  0  0  1
+  // 1  2  4  8  16
+  // 1  1  1  1  1
+  // 16 8  4  2  1
+  // 1  0  0  0  0
+  //   
+  // using 12 subtractions, 4 shifts, 
+  // 2 small divisions and 1 small multiplication 
+   
+  // r1 - r4
+  w1 -= w4;
+  // r3 - r0
+  w3 -= w0;
+  // r1/2
+  w1.divide_by_2();
+  // r3/2
+  w3.divide_by_2();
+  // r2 - r0 - r4
+  w2 -= w0;
+  w2 -= w4;
+  // r1 - r2
+  w1 -= w2;
+  // r3 - r2
+  w3 -= w2;
+  // r1 - 8r0
+  tmp1 = w0 << 3;
+  w1 -= tmp1;
+  // r3 - 8r4
+  tmp1 = w4 << 3;
+  w3 -= tmp1;
+  // 3r2 - r1 - r3
+  w2.multiply_by_digit(3);
+  w2 -= w1;
+  w2 -= w3;
+  // r1 - r2
+  w1 -= w2;
+  // r3 - r2
+  w3 -= w2;
+  // r1/3
+  w1.divide_by_3();
+  // r3/3
+  w3.divide_by_3();
+
+  // at this point shift W[n] by B*n
+  w1.shift_digits_left(1*B);
+  w2.shift_digits_left(2*B);
+  w3.shift_digits_left(3*B);
+  w4.shift_digits_left(4*B);
+
+  *this = w0 + w1;
+  tmp1 = w2 + w3;
+  tmp1 += w4;
+  *this += tmp1;
+}
+
+// c = |a| * |b| using Karatsuba Multiplication using 
+// three half size multiplications
+//
+// Let B represent the radix [e.g. 2**valid_bits] and 
+// let n represent half of the number of digits in 
+// the min(a,b)
+//
+// a = x1 * B**n + x0
+// b = y1 * B**n + y0
+//
+// Then, a * b => 
+// x1y1 * B**2n + ((x1 + x0)(y1 + y0) - (x0y0 + x1y1)) * B + x0y0
+//
+// Note that x1y1 and x0y0 are used twice and only need to be 
+// computed once.  So in total three half size (half # of 
+// digit) multiplications are performed, x0y0, x1y1 and 
+// (x1+y1)(x0+y0)
+//
+// Note that a multiplication of half the digits requires
+// 1/4th the number of single precision multiplications so in 
+// total after one call 25% of the single precision multiplications 
+// are saved.  Note also that the call to mp_mul can end up back 
+// in this function if the x0, x1, y0, or y1 are above the threshold.  
+// This is known as divide-and-conquer and leads to the famous 
+// O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 
+// the standard O(N**2) that the baseline/comba methods use.  
+// Generally though the overhead of this method doesn't pay off 
+// until a certain size (N ~ 80) is reached.
+template<class A, class T>
+void mp_int<A,T>::karatsuba_mul(const mp_int& b)
+{
+  mp_int x0, x1, y0, y1, /*tmp,*/ x0y0, x1y1;
+
+  // min # of digits
+  const size_type B = std::min(used_, b.used_) / 2;
+
+  // allocate memory
+  x0.grow_capacity(B);
+  x1.grow_capacity(used_ + b.used_);
+  y0.grow_capacity(B);
+  y1.grow_capacity(b.used_ - B + 1);
+
+  // set used_ count
+  x0.used_ = y0.used_ = B;
+  x1.used_ = used_ - B;
+  y1.used_ = b.used_ - B;
+
+  // copy digits over
+  static const size_type s = sizeof(digit_type);
+  std::memcpy(x0.digits_, digits_,   s * B);
+  std::memcpy(y0.digits_, b.digits_, s * B);
+  std::memcpy(x1.digits_, digits_ + B,   s * (  used_ - B));
+  std::memcpy(y1.digits_, b.digits_ + B, s * (b.used_ - B));
+
+  // only need to clamp the lower words since by definition the 
+  // upper words x1/y1 must have a known number of digits
+  x0.clamp();
+  y0.clamp();
+
+  // now evaluate the term
+  // x1y1 * B**2n + ((x1 + x0)(y1 + y0) - (x0y0 + x1y1)) * B + x0y0
+  
+  // first calc the products x0y0 and x1y1
+  x0y0 = x0 * y0;
+  x1y1 = x1 * y1;
+
+  // tmp = (x1 + x0) * (y1 + y0)
+  x1.add_magnitude(x0);
+  y1.add_magnitude(y0);
+  // we don't need a tmp just reuse x1
+  x1 *= y1;
+
+  // tmp -= (x0y0 + x1y1);
+  x1.sub_smaller_magnitude(x0y0);
+  x1.sub_smaller_magnitude(x1y1);
+
+  // shift by B
+  x1.shift_digits_left(B);
+  x1y1.shift_digits_left(B * 2);
+
+  x1.add_magnitude(x0y0);
+  x1.add_magnitude(x1y1);
+  swap(x1);
+}
+
+
+// multiplies |a| * |b| and only computes up to digs digits of result
+// HAC pp. 595, Algorithm 14.12  Modified so you can control how 
+// many digits of output are created.
+template<class A, class T>
+void mp_int<A,T>::mul_digits(const mp_int& b, size_type digs)
+{
+  mp_int tmp;
+  tmp.grow_capacity(digs);
+  // zero allocated digits
+  std::memset(tmp.digits_, 0, sizeof(digit_type) * digs);
+  tmp.used_ = digs;
+
+  // compute the digits of the product directly
+  for (size_type i = 0; i < used_; ++i)
+  {
+    digit_type carry = 0;
+
+    // limit ourselves to making digs digits of output
+    const size_type pb = std::min(b.used_, digs - i);
+
+    // compute the columns of the output and propagate the carry
+    for (size_type j = 0; j < pb; ++j)
+    {
+      // compute the column as a word_type
+      const word_type r = static_cast<word_type>(tmp.digits_[i+j])
+                        + static_cast<word_type>(digits_[i])
+                        * static_cast<word_type>(b.digits_[j])
+                        + static_cast<word_type>(carry);
+
+      // the new column is the lower part of the result
+      tmp.digits_[i+j] = static_cast<digit_type>(r);
+
+      // get the carry word from the result
+      carry = static_cast<digit_type>(r >> static_cast<word_type>(valid_bits));
+    }
+    // set carry if it is placed below digs
+    if (i + pb < digs)
+      tmp.digits_[i+pb] = carry;
+  }
+
+  tmp.clamp();
+  if (tmp.is_zero())
+    tmp.sign_ = 1;
+  swap(tmp);
+}
+
+// FIXME no routine seems to use this
+//
+// multiplies |a| * |b| and does not compute the lower digs digits
+// [meant to get the higher part of the product]
+template<class A, class T>
+void mp_int<A,T>::mul_high_digits(const mp_int& b, size_type digs)
+{
+  mp_int tmp;
+  tmp.grow_capacity(used_ + b.used_ + 1);
+  tmp.used_ = used_ + b.used_ + 1;
+  std::memset(tmp.digits_, 0, sizeof(digit_type) * tmp.used_);
+
+  for (size_type i = 0; i < used_; ++i)
+  {
+    digit_type* dst = tmp.digits_ + digs;
+    digit_type* z   = b.digits_ + (digs - i);
+    digit_type carry = 0;
+
+    for (size_type j = digs - i; j < b.used_; ++j)
+    {
+      const word_type r = static_cast<word_type>(*dst)
+                        + static_cast<word_type>(digits_[i])
+                        * static_cast<word_type>(*z++)
+                        + static_cast<word_type>(carry);
+
+      // get the lower part
+      *dst++ = static_cast<digit_type>(r);
+
+      // update carry
+      carry = static_cast<digit_type>(r >> valid_bits);
+    }
+    *dst = carry;
+  }
+
+  tmp.clamp();
+  if (tmp.is_zero())
+    tmp.sign_ = 1;
+  swap(tmp);
+}
+
+
+// this is a modified version of fast_s_mul_digs that only produces
+// output digits *above* digs.  See the comments for fast_s_mul_digs
+// to see how it works.
+//
+// This is used in the Barrett reduction since for one of the multiplications
+// only the higher digits were needed. This essentially halves the work.
+//
+// Based on Algorithm 14.12 on pp.595 of HAC.
+template<class A, class T>
+void mp_int<A,T>::fast_mul_high_digits(const mp_int& b, size_type digs)
+{
+  mul_high_digits(b, digs);
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/numeric_limits.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/numeric_limits.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,52 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace std
+{
+
+template<class A, class T>
+class numeric_limits<boost::mp_math::mp_int<A,T> >
+{
+public:
+
+  static const bool is_specialized = true;
+  static boost::mp_math::mp_int<A,T> min() throw() { return boost::mp_math::mp_int<A,T>(0U); }
+  static boost::mp_math::mp_int<A,T> max() throw() { return boost::mp_math::mp_int<A,T>(0U); }
+
+  static const int  digits   = 0;
+  static const int  digits10 = 0;
+  static const bool is_signed  = true;
+  static const bool is_integer = true;
+  static const bool is_exact   = true;
+  static const int  radix      = 2;
+  static boost::mp_math::mp_int<A,T> epsilon    () throw() { return boost::mp_math::mp_int<A,T>(0U); }
+  static boost::mp_math::mp_int<A,T> round_error() throw() { return boost::mp_math::mp_int<A,T>(0U); }
+
+  static const int  min_exponent   = 0;
+  static const int  min_exponent10 = 0;
+  static const int  max_exponent   = 0;
+  static const int  max_exponent10 = 0;
+
+  static const bool has_infinity      = false;
+  static const bool has_quiet_NaN     = false;
+  static const bool has_signaling_NaN = false;
+  static const float_denorm_style has_denorm = denorm_absent;
+  static const bool has_denorm_loss   = false;
+  static boost::mp_math::mp_int<A,T> infinity     () throw() { return boost::mp_math::mp_int<A,T>(0U); }
+  static boost::mp_math::mp_int<A,T> quiet_NaN    () throw() { return boost::mp_math::mp_int<A,T>(0U); }
+  static boost::mp_math::mp_int<A,T> signaling_NaN() throw() { return boost::mp_math::mp_int<A,T>(0U); }
+  static boost::mp_math::mp_int<A,T> denorm_min   () throw() { return boost::mp_math::mp_int<A,T>(0U); }
+
+  static const bool is_iec559  = false;
+  static const bool is_bounded = false;
+  static const bool is_modulo  = false;
+
+  static const bool traps = false;
+  static const bool tinyness_before = false;
+  static const float_round_style round_style = round_toward_zero;
+};
+
+} // namespace std
+
Added: sandbox/mp_math/boost/mp_math/mp_int/operators.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/operators.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,1148 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// compare mp_int to mp_int
+template<class A, class T>
+inline bool
+operator == (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  return lhs.sign_ == rhs.sign_ && lhs.used_ == rhs.used_ &&
+    std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template<class A, class T>
+inline bool
+operator != (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)  { return !(lhs == rhs); }
+
+template<class A, class T>
+bool
+operator < (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  /* compare based on sign */
+  if (lhs.sign_ != rhs.sign_)
+  {
+    if (lhs.is_negative())
+      return true;
+    else
+      return false;
+  }
+
+  if (lhs.size() < rhs.size())
+    return true;
+  if (lhs.size() > rhs.size())
+    return false;
+  
+  /* compare digits */
+  if (lhs.is_negative())
+    return std::lexicographical_compare(
+      rhs.rbegin(), rhs.rend(), lhs.rbegin(), lhs.rend());
+  else
+    return std::lexicographical_compare(
+      lhs.rbegin(), lhs.rend(), rhs.rbegin(), rhs.rend());
+}
+
+template<class A, class T>
+inline bool
+operator > (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs) { return rhs < lhs; }
+
+template<class A, class T>
+inline bool
+operator <= (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)  { return !(rhs < lhs);  }
+
+template<class A, class T>
+inline bool
+operator >= (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)  { return !(lhs < rhs);  }
+
+
+// compare mp_int to integral
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  return detail::integral_ops<IntegralT>::equal(lhs, rhs);
+}
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (const mp_int<A,T>& lhs, IntegralT rhs) { return !(lhs == rhs); }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator < (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  return detail::integral_ops<IntegralT>::less(lhs, rhs);
+}
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (const mp_int<A,T>& lhs, IntegralT rhs)  { return rhs < lhs; }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator <= (const mp_int<A,T>& lhs, IntegralT rhs) { return (lhs < rhs) || (lhs == rhs);  }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator >= (const mp_int<A,T>& lhs, IntegralT rhs) { return !(lhs < rhs);  }
+
+// compare integral to mp_int
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (IntegralT lhs, const mp_int<A,T>& rhs) { return rhs == lhs;  }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (IntegralT lhs, const mp_int<A,T>& rhs) { return !(lhs == rhs); }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator < (IntegralT lhs, const mp_int<A,T>& rhs)  { return !(rhs <= lhs); }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (IntegralT lhs, const mp_int<A,T>& rhs)  { return rhs < lhs; }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator <= (IntegralT lhs, const mp_int<A,T>& rhs) { return !(rhs < lhs);  }
+
+template<class A, class T, typename IntegralT>
+inline typename enable_if<is_integral<IntegralT>, bool>::type
+operator >= (IntegralT lhs, const mp_int<A,T>& rhs) { return rhs <= lhs;  }
+
+
+// compare mp_int to const char*
+template<class A, class T>
+inline bool
+operator == (const mp_int<A,T>& lhs, const char* rhs) { return lhs == mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator != (const mp_int<A,T>& lhs, const char* rhs) { return lhs != mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator < (const mp_int<A,T>& lhs, const char* rhs) { return lhs < mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator > (const mp_int<A,T>& lhs, const char* rhs) { return lhs > mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator <= (const mp_int<A,T>& lhs, const char* rhs) { return lhs <= mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator >= (const mp_int<A,T>& lhs, const char* rhs) { return lhs >= mp_int<A,T>(rhs); }
+
+// compare const char* to mp_int
+template<class A, class T>
+inline bool
+operator == (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) == rhs; }
+
+template<class A, class T>
+inline bool
+operator != (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) != rhs; }
+
+template<class A, class T>
+inline bool
+operator < (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) < rhs; }
+
+template<class A, class T>
+inline bool
+operator > (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) > rhs; }
+
+template<class A, class T>
+inline bool
+operator <= (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) <= rhs; }
+
+template<class A, class T>
+inline bool
+operator >= (const char* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) >= rhs; }
+
+
+#ifndef BOOST_NO_CWCHAR
+// compare mp_int to const wchar_t*
+template<class A, class T>
+inline bool
+operator == (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs == mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator != (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs != mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator < (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs < mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator > (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs > mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator <= (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs <= mp_int<A,T>(rhs); }
+
+template<class A, class T>
+inline bool
+operator >= (const mp_int<A,T>& lhs, const wchar_t* rhs) { return lhs >= mp_int<A,T>(rhs); }
+
+// compare const wchar_t* to mp_int
+template<class A, class T>
+inline bool
+operator == (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) == rhs; }
+
+template<class A, class T>
+inline bool
+operator != (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) != rhs; }
+
+template<class A, class T>
+inline bool
+operator < (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) < rhs; }
+
+template<class A, class T>
+inline bool
+operator > (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) > rhs; }
+
+template<class A, class T>
+inline bool
+operator <= (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) <= rhs; }
+
+template<class A, class T>
+inline bool
+operator >= (const wchar_t* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) >= rhs; }
+#endif // BOOST_NO_CWCHAR
+
+
+// compare mp_int to basic_string
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator == (const mp_int<A,T>& lhs, const std::basic_string<charT,Traits,Alloc>& rhs) { return lhs == mp_int<A,T>(rhs); }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator != (const mp_int<A,T>& lhs, const std::basic_string<charT,Traits,Alloc>& rhs) { return lhs != mp_int<A,T>(rhs); }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator < (const mp_int<A,T>& lhs, const std::basic_string<charT,Traits,Alloc>& rhs) { return lhs < mp_int<A,T>(rhs); }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator > (const mp_int<A,T>& lhs, const std::basic_string<charT,Traits,Alloc>& rhs) { return lhs > mp_int<A,T>(rhs); }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const mp_int<A,T>& lhs, const std::basic_string<charT,Traits,Alloc>& rhs) { return lhs <= mp_int<A,T>(rhs); }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const mp_int<A,T>& lhs, const std::basic_string<charT,Traits,Alloc>& rhs) { return lhs >= mp_int<A,T>(rhs); }
+
+// compare basic_string to mp_int
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator == (const std::basic_string<charT,Traits,Alloc>& lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) == rhs; }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator != (const std::basic_string<charT,Traits,Alloc>& lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) != rhs; }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator < (const std::basic_string<charT,Traits,Alloc>& lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) < rhs; }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator > (const std::basic_string<charT,Traits,Alloc>& lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) > rhs; }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const std::basic_string<charT,Traits,Alloc>& lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) <= rhs; }
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const std::basic_string<charT,Traits,Alloc>& lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) >= rhs; }
+
+
+
+
+// prefix ops
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator ++()
+{
+  add_digit(1);
+  return *this;
+}
+
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator --()
+{
+  sub_digit(1);
+  return *this;
+}
+
+// postfix ops
+template<class A, class T>
+inline mp_int<A,T> mp_int<A,T>::operator ++(int)
+{
+  mp_int<A,T> tmp(*this);
+  ++(*this);
+  return tmp;
+}
+
+template<class A, class T>
+inline mp_int<A,T> mp_int<A,T>::operator --(int)
+{
+  mp_int<A,T> tmp(*this);
+  --(*this);
+  return tmp;
+}
+
+// shift ops
+// this function corresponds to mp_mul_2d()
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator <<= (size_type b)
+{
+  grow_capacity(used_ + b/valid_bits + 1);
+
+  /* shift by as many digits in the bit count */
+  if (b >= static_cast<size_type>(valid_bits))
+    shift_digits_left(b / valid_bits);
+
+  /* shift any bit count < valid_bits */
+  const digit_type d = static_cast<digit_type>(b % valid_bits);
+  
+  if (d)
+  {
+    /* bitmask for carries */
+    const digit_type mask = (digit_type(1) << d) - 1;
+
+    /* shift for msbs */
+    const digit_type shift = valid_bits - d;
+
+    digit_type carry = 0;
+    for (size_type i = 0; i < used_; ++i)
+    {
+      /* get the higher bits of the current word */
+      const digit_type carry_cur = (digits_[i] >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      digits_[i] = (digits_[i] << d) | carry;
+
+      /* set the carry to the carry bits of the current word */
+      carry = carry_cur;
+    }
+    
+    if (carry)
+      digits_[used_++] = carry;
+  }
+
+  clamp();
+  return *this;
+}
+
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator >>= (size_type b)
+{
+  shift_right(b, 0);
+  return *this;
+}
+
+// unary negate
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator - ()
+{
+  if (!is_zero())
+    sign_ = sign_ == 1 ? -1 : 1;
+  return *this;
+}
+
+
+// arithmetic
+
+
+// this is the high level addition function
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator += (const mp_int<A,T>& rhs)
+{
+  if (sign_ == rhs.sign_)
+    add_magnitude(rhs);
+  else
+  {
+    // subtract the one with the lesser magnitude from
+    // the one of the greater magnitude. The result gets
+    // the sign of the one with the greater magnitude.
+    const mp_int* x;
+    const mp_int* y;
+    if (compare_magnitude(rhs) != -1) // |*this| >= |rhs|
+    {
+      x = this;
+      y = &rhs;
+    }
+    else // |*this| < |rhs|
+    {
+      grow_capacity(rhs.used_);
+      sign_ = rhs.sign_;
+      x = &rhs;
+      y = this;
+    }
+
+    ops_type::sub_smaller_magnitude(digits_, x->digits_, x->used_,
+                                             y->digits_, y->used_);
+    used_ = x->used_;
+
+    clamp();
+    if (is_zero())
+      sign_ = 1;
+  }
+  return *this;
+}
+
+// high level subtraction (handles signs)
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator -= (const mp_int<A,T>& rhs)
+{
+  if (sign_ != rhs.sign_)
+    // add magnitudes, and use the sign of *this.
+    add_magnitude(rhs);
+  else
+  {
+    const mp_int* x;
+    const mp_int* y;
+    if (compare_magnitude(rhs) != -1) // [*this] >= rhs
+    {
+      x = this;
+      y = &rhs;
+    }
+    else // |*this| < |rhs|
+    {
+      grow_capacity(rhs.used_);
+      // result has opposite sign from *this
+      sign_ = is_positive() ? -1 : 1; 
+      x = &rhs;
+      y = this;
+    }
+    
+    ops_type::sub_smaller_magnitude(digits_, x->digits_, x->used_,
+                                             y->digits_, y->used_);
+
+    used_ = x->used_;
+    
+    clamp();
+    if (is_zero())
+      sign_ = 1;
+  }
+  return *this;
+}
+
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator *= (const mp_int<A,T>& rhs)
+{
+  if (this == &rhs)
+  {
+    sqr();
+    return *this;
+  }
+  
+  const int neg = (sign_ == rhs.sign_) ? 1 : -1;
+  const size_type min = std::min(used_, rhs.used_);
+
+  if (min >= traits_type::toom_mul_cutoff)
+    toom_cook_mul(rhs);
+  else if (min >= traits_type::karatsuba_mul_cutoff)
+    karatsuba_mul(rhs);
+  else
+  {
+    mp_int tmp;
+    tmp.grow_capacity(used_ + rhs.used_);
+    
+    if (used_ == rhs.used_)
+      ops_type::comba_mul(tmp.digits(), digits(), rhs.digits(), used_);
+    else
+    {
+      // always multiply larger by smaller number
+      const mp_int* a = this;
+      const mp_int* b = &rhs;
+      if (a->used_ < b->used_)
+        std::swap(a, b);
+
+      ops_type::comba_mul(tmp.digits(), a->digits(), a->used_, b->digits(), b->used_);
+    }
+
+    tmp.used_ = used_ + rhs.used_;
+    tmp.clamp();
+    swap(tmp);
+  }
+
+  sign_ = is_zero() ? 1 : neg;
+
+  return *this;
+}
+
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator /= (const mp_int<A,T>& rhs)
+{
+  divide(rhs, 0);
+  return *this;
+}
+
+// The sign of the result is the sign of the dividend, i.e. *this.
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator %= (const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> remainder;
+  divide(rhs, &remainder);
+  swap(remainder);
+  return *this;
+}
+
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator |= (const mp_int<A,T>& rhs)
+{
+  size_type px;
+  mp_int tmp;
+  const mp_int* x;
+
+  if (used_ > rhs.used_)
+  {
+    tmp = *this;
+    px = rhs.used_;
+    x = &rhs;
+  }
+  else
+  {
+    tmp = rhs;
+    px = used_;
+    x = this;
+  }
+  
+  for (size_type i = 0; i < px; ++i)
+    tmp[i] |= (*x)[i];
+  
+  tmp.clamp();
+  swap(tmp);
+  
+  return *this;
+}
+
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator &= (const mp_int<A,T>& rhs)
+{
+  size_type px;
+  mp_int tmp;
+  const mp_int *x;
+
+  if (used_ > rhs.used_)
+  {
+    tmp = *this;
+    px = rhs.used_;
+    x = &rhs;
+  }
+  else
+  {
+    tmp = rhs;
+    px = used_;
+    x = this;
+  }
+
+  for (size_type i = 0; i < px; ++i)
+    tmp[i] &= (*x)[i];
+  
+  /* zero digits above the last from the smallest mp_int */
+  std::memset(tmp.digits_ + px, 0, (tmp.used_ - px) * sizeof(digit_type));
+  tmp.clamp();
+  swap(tmp);
+  
+  return *this;
+}
+
+template<class A, class T>
+mp_int<A,T>& mp_int<A,T>::operator ^= (const mp_int<A,T>& rhs)
+{
+  size_type px;
+  mp_int tmp;
+  const mp_int *x;
+
+  if (used_ > rhs.used_)
+  {
+    tmp = *this;
+    px = rhs.used_;
+    x = &rhs;
+  }
+  else
+  {
+    tmp = rhs;
+    px = used_;
+    x = this;
+  }
+
+  for (size_type i = 0; i < px; ++i)
+    tmp[i] ^= (*x)[i];
+  
+  tmp.clamp();
+  swap(tmp);
+  
+  return *this;
+}
+
+template<class A, class T>
+inline mp_int<A,T>
+operator << (const mp_int<A,T>& lhs, typename mp_int<A,T>::size_type b)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv <<= b;
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T>
+operator >> (const mp_int<A,T>& lhs, typename mp_int<A,T>::size_type b)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv >>= b;
+  return nrv;
+}
+
+
+template<class A, class T>
+inline mp_int<A,T> operator - (const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(rhs);
+  -nrv;
+  return nrv;
+}
+
+
+
+template<class A, class T>
+inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv += rhs;
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv -= rhs;
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  if (&lhs != &rhs)
+    nrv *= rhs;
+  else
+    nrv *= nrv; // this uses special squaring code in operator *=
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv /= rhs;
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv %= rhs;
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv |= rhs;
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv &= rhs;
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, const mp_int<A,T>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv ^= rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv += rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv -= rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv *= rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv /= rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv %= rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv |= rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv &= rhs;
+  return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, IntegralT rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv ^= rhs;
+  return nrv;
+}
+
+
+// Arithmetic and bitwise operators involving const char*
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator += (const char* s) { return *this += mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator -= (const char* s) { return *this -= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator *= (const char* s) { return *this *= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator /= (const char* s) { return *this /= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator %= (const char* s) { return *this %= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator |= (const char* s) { return *this |= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator &= (const char* s) { return *this &= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator ^= (const char* s) { return *this ^= mp_int<A,T>(s); }
+
+template<class A, class T>
+inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv += mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv -= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv *= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv /= mp_int<A,T>(rhs);
+  return nrv;
+}
+template<class A, class T>
+inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv %= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv |= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv &= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, const char* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv ^= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+
+#ifndef BOOST_NO_CWCHAR
+// Arithmetic and bitwise operators involving const wchar_t*
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator += (const wchar_t* s) { return *this += mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator -= (const wchar_t* s) { return *this -= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator *= (const wchar_t* s) { return *this *= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator /= (const wchar_t* s) { return *this /= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator %= (const wchar_t* s) { return *this %= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator |= (const wchar_t* s) { return *this |= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator &= (const wchar_t* s) { return *this &= mp_int<A,T>(s); }
+template<class A, class T>
+inline mp_int<A,T>& mp_int<A,T>::operator ^= (const wchar_t* s) { return *this ^= mp_int<A,T>(s); }
+
+template<class A, class T>
+inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv += mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv -= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv *= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv /= mp_int<A,T>(rhs);
+  return nrv;
+}
+template<class A, class T>
+inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv %= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv |= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv &= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T>
+inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, const wchar_t* rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv ^= mp_int<A,T>(rhs);
+  return nrv;
+}
+#endif // BOOST_NO_CWCHAR
+
+
+// Arithmetic and bitwise operators involving basic_string
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator += (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this += mp_int<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator -= (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this -= mp_int<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator *= (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this *= mp_int<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator /= (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this /= mp_int<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator %= (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this %= mp_int<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator |= (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this |= mp_int<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator &= (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this &= mp_int<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline mp_int<A,T>&
+mp_int<A,T>::operator ^= (const std::basic_string<charT,traits,Alloc>& s)
+{
+  return *this ^= mp_int<A,T>(s);
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator + (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv += mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator - (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv -= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator * (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv *= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator / (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv /= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator % (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv %= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator | (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv |= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator & (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv &= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline mp_int<A,T>
+operator ^ (const mp_int<A,T>& lhs, const std::basic_string<charT,traits,Alloc>& rhs)
+{
+  mp_int<A,T> nrv(lhs);
+  nrv ^= mp_int<A,T>(rhs);
+  return nrv;
+}
+
+
+
+
+// Input/Output
+template<class A, class T, typename charT, class traits>
+std::basic_istream<charT, traits>&
+operator >> (std::basic_istream<charT, traits>& is, mp_int<A,T>& x)
+{
+  typename std::basic_istream<charT, traits>::sentry sentry(is);
+  if (!sentry)
+    return is;
+
+  std::string s;
+
+  const std::istreambuf_iterator<charT, traits> end;
+  std::istreambuf_iterator<charT, traits> c(is);
+
+  if (*c == '+' || *c == '-')
+  {
+    s.push_back(*c);
+    ++c;
+  }
+
+  int base;
+  if (*c == '0')
+  {
+    base = 8;
+    s.push_back(*c);
+    ++c;
+    if (*c == 'x' || *c == 'X')
+    {
+      base = 16;
+      s.push_back(*c);
+      ++c;
+    }
+  }
+  else if (*c >= '0' && *c <= '9')
+    base = 10;
+  else
+  {
+    is.setstate(std::ios_base::failbit);
+    return is;
+  }
+
+  switch (base)
+  {
+    case 8:
+      while (c != end)
+      {
+        if (*c >= '0' && *c <= '7')
+          s.push_back(*c);
+        else
+          break;
+        ++c;
+      }
+      break;
+    case 10:
+      while (c != end)
+      {
+        if (*c >= '0' && *c <= '9')
+          s.push_back(*c);
+        else
+          break;
+        ++c;
+      }
+      break;
+    case 16:
+      while (c != end)
+      {
+        if ((*c >= '0' && *c <= '9') ||
+            (*c >= 'A' && *c <= 'F') ||
+            (*c >= 'a' && *c <= 'f'))
+          s.push_back(*c);
+        else
+          break;
+        ++c;
+      }
+      break;
+  }
+
+  const mp_int<A,T> tmp(s.begin(), s.end());
+  x = tmp;
+
+  return is;
+}
+
+template<class A, class T, typename charT, class traits>
+std::basic_ostream<charT, traits>&
+operator << (std::basic_ostream<charT, traits>& os, const mp_int<A,T>& x)
+{
+  return os << x.template to_string<std::string>(os.flags());
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/pow.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/pow.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,496 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* computes a = 2**b 
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+template<class A, class T>
+void mp_int<A,T>::pow2(typename mp_int<A,T>::size_type b)
+{
+  /* grow a to accomodate the single bit */
+  grow_capacity(b / digit_bits + 1);
+
+  /* set the used count of where the bit will go */
+  used_ = b / digit_bits + 1;
+
+  // set all bits to zero
+  std::memset(digits_, 0, used_ * sizeof(digit_type));
+  
+  /* put the single bit in its place */
+  digits_[b / digit_bits] = digit_type(1) << (b % digit_bits);
+}
+
+/* calculate c = a**b  using a square-multiply algorithm */
+template<class A, class T>
+void mp_int<A,T>::pow(digit_type b)
+{
+  mp_int g(*this);
+
+  /* set initial result */
+  *this = digit_type(1);
+
+  for (int x = 0; x < digit_bits; ++x)
+  {
+    sqr();
+
+    /* if the bit is set multiply */
+    if (b & (digit_type(1) << (digit_bits - 1)))
+      *this *= g;
+
+    /* shift to next bit */
+    b <<= 1;
+  }
+}
+
+// this is a shell function that calls either the normal or Montgomery
+// modpow functions. Originally the call to the montgomery code was
+// embedded in the normal function but that wasted alot of stack space
+// for nothing (since 99% of the time the Montgomery code would be called)
+//
+// y = g^x mod p
+// *this = *this^exp mod m
+template<class A, class T>
+void mp_int<A,T>::modpow(const mp_int& exp, const mp_int& m)
+{
+  if (m.is_negative())
+    throw std::domain_error("modpow: modulus m must be positive");
+
+  if (exp.is_negative())
+  {
+    // first compute 1 / *this mod m
+    modinv(m);
+
+    // and now compute (1 / *this)**|exp| instead of *this**exp [exp < 0]
+    modpow(abs(exp), m);
+    return;
+  }
+
+  /* modified diminished radix reduction */
+  if (m.reduce_is_2k_l())
+  {
+    //std::cout << "barret_modpow1\n";
+    barret_modpow(exp, m, 1);
+    return;
+  }
+
+  /* is it a DR modulus? */
+  int dr = m.is_dr_modulus();
+
+  /* if not, is it a unrestricted DR modulus? */
+  if (!dr)
+    dr = m.reduce_is_2k() << 1;
+    
+  /* if the modulus is odd or dr == true use the montgomery method */
+  if (m.is_odd() || dr)
+  {
+    //std::cout << "fast_modpow dr = " << dr << "\n";
+    fast_modpow(exp, m, dr);
+  }
+  else
+  {
+    //std::cout << "barret_modpow2\n";
+    /* otherwise use the generic Barrett reduction technique */
+    barret_modpow(exp, m, 0);
+  }
+}
+
+template<class A, class T>
+void mp_int<A,T>::barret_modpow(const mp_int& exp, const mp_int& m, int redmode)
+{
+  static const int TAB_SIZE = 256;
+  mp_int M[TAB_SIZE];
+
+  void (mp_int::*redux)(const mp_int&, const mp_int&);
+
+  /* find window size */
+  size_type x = exp.precision();
+  size_type winsize;
+  if (x <= 7)
+    winsize = 2;
+  else if (x <= 36)
+    winsize = 3;
+  else if (x <= 140)
+    winsize = 4;
+  else if (x <= 450)
+    winsize = 5;
+  else if (x <= 1303)
+    winsize = 6;
+  else if (x <= 3529)
+    winsize = 7;
+  else
+    winsize = 8;
+
+  /* create mu, used for Barrett reduction */
+  mp_int mu;
+
+  mp_int mm(m);
+  if (redmode == 0)
+  {
+    mu.reduce_setup(m);
+    //std::cout << "redux = reduce\n";
+    redux = &mp_int::reduce;
+  }
+  else
+  {
+    mu = mm.reduce_2k_l_setup();
+    //std::cout << "redux = reduce_2k_l\n";
+    redux = &mp_int::reduce_2k_l;
+  }
+
+  /* create M table
+   *
+   * The M table contains powers of the base, 
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not 
+   * computed though accept for M[0] and M[1]
+   */
+  M[1] = *this % mm;
+
+
+  /* compute the value at M[1<<(winsize-1)] by squaring 
+   * M[1] (winsize-1) times 
+   */
+  M[1 << (winsize - 1)] = M[1];
+
+  for (x = 0; x < (winsize - 1); x++)
+  {
+    /* square it */
+    M[1 << (winsize - 1)].sqr();
+    /* reduce modulo P */
+    (M[1 << (winsize - 1)].*redux)(mm, mu);
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (size_type(1) << winsize); ++x)
+  {
+    M[x] = M[x-1] * M[1];
+    (M[x].*redux)(mm, mu);
+  }
+
+  /* setup result */
+  mp_int res = digit_type(1);
+
+  /* set initial mode and bit cnt */
+  int mode   = 0;
+  int bitcnt = 1;
+  digit_type buf = 0;
+  int digidx = exp.used_ - 1;
+  size_type bitcpy = 0;
+  int bitbuf = 0;
+
+  for (;;)
+  {
+    /* grab next digit as required */
+    if (--bitcnt == 0)
+    {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1)
+        break;
+      /* read next digit and reset the bitcnt */
+      buf    = exp.digits_[digidx--];
+      bitcnt = valid_bits;
+    }
+
+    /* grab the next msb from the exponent */
+    int y = (buf >> static_cast<digit_type>(valid_bits - 1)) & 1;
+    buf <<= digit_type(1);
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent. Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0)
+      continue;
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0)
+    {
+      res.sqr();
+      (res.*redux)(mm, mu);
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize)
+    {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; ++x)
+      {
+        res.sqr();
+        (res.*redux)(mm, mu);
+      }
+
+      /* then multiply */
+      res *= M[bitbuf];
+      (res.*redux)(mm, mu);
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0)
+  {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; ++x)
+    {
+      res.sqr();
+      (res.*redux)(mm, mu);
+      //mu = res * mm;
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0)
+      {
+        /* then multiply */
+        res *= M[1];
+        (res.*redux)(mm, mu);
+      }
+    }
+  }
+
+  swap(res);
+}
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+template<class A, class T>
+void mp_int<A,T>::fast_modpow(const mp_int& exp, const mp_int& m, int redmode)
+{
+  static const int TAB_SIZE = 256;
+  mp_int M[TAB_SIZE];
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  void (mp_int::*redux)(const mp_int&, digit_type);
+  
+  /* find window size */
+  size_type x = exp.precision();
+  size_type winsize;
+  if (x <= 7)
+    winsize = 2;
+  else if (x <= 36)
+    winsize = 3;
+  else if (x <= 140)
+    winsize = 4;
+  else if (x <= 450)
+    winsize = 5;
+  else if (x <= 1303)
+    winsize = 6;
+  else if (x <= 3529)
+    winsize = 7;
+  else
+    winsize = 8;
+  
+  digit_type mp;
+  /* determine and setup reduction code */
+  if (redmode == 0)
+  {
+    /* now setup montgomery  */
+    mp = m.montgomery_setup();
+
+    /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+    /*if (((m.used_ * 2 + 1) < mp_warray) &&
+         m.used_ < 1 << ((CHAR_BIT * sizeof(word_type)) - (2 * valid_bits)))
+    {
+      std::cout << "redux = fast_montgomery_reduce\n";
+      redux = &mp_int::fast_montgomery_reduce;
+    }
+    else 
+    {*/
+      /* use slower baseline Montgomery method */
+      //std::cout << "redux = montgomery_reduce\n";
+      redux = &mp_int::montgomery_reduce;
+    //}
+  }
+  else if (redmode == 1)
+  {
+    /* setup DR reduction for moduli of the form B**k - b */
+    mp = m.dr_setup();
+    redux = &mp_int::dr_reduce;
+  }
+  else
+  {
+    /* setup DR reduction for moduli of the form 2**k - b */
+    mp = m.reduce_2k_setup();
+    redux = &mp_int::reduce_2k;
+  }
+
+  /* setup result */
+  mp_int res;
+
+  /* create M table
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+  if (redmode == 0)
+  {
+    /* now we need R mod m */
+    res.montgomery_calc_normalization(m);
+    /* now set M[1] to G * R mod m */
+    M[1] = (*this * res) % m;
+  }
+  else
+  {
+    res = digit_type(1);
+    M[1] = *this % m;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  M[1 << (winsize - 1)] = M[1];
+
+  for (x = 0; x < (winsize - 1); ++x)
+  {
+    M[1 << (winsize - 1)].sqr();
+    (M[1 << (winsize - 1)].*redux)(m, mp);
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (size_type(1) << winsize); ++x)
+  {
+    M[x] = M[x-1] * M[1];
+    (M[x].*redux)(m, mp);
+  }
+
+  /* set initial mode and bit cnt */
+  int mode   = 0;
+  int bitcnt = 1;
+  digit_type buf = 0;
+  int digidx = exp.used_ - 1;
+  size_type bitcpy = 0;
+  unsigned int bitbuf = 0;
+
+  for (;;)
+  {
+    /* grab next digit as required */
+    if (--bitcnt == 0)
+    {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1)
+        break;
+      /* read next digit and reset bitcnt */
+      buf    = exp.digits_[digidx--];
+      bitcnt = valid_bits;
+    }
+
+    /* grab the next msb from the exponent */
+    int y = (buf >> (valid_bits - 1)) & 1;
+    buf <<= digit_type(1);
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0)
+      continue;
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0)
+    {
+      res.sqr();
+      (res.*redux)(m, mp);
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize)
+    {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; ++x)
+      {
+        res.sqr();
+        (res.*redux)(m, mp);
+      }
+
+      /* then multiply */
+      res *= M[bitbuf];
+      (res.*redux)(m, mp);
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0)
+  {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; ++x)
+    {
+      res.sqr();
+      (res.*redux)(m, mp);
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0)
+      {
+        /* then multiply */
+        res *= M[1];
+        (res.*redux)(m, mp);
+      }
+    }
+  }
+
+  /* fixup result if Montgomery reduction is used
+   * recall that any value in a Montgomery system is
+   * actually multiplied by R mod n.  So we have
+   * to reduce one more time to cancel out the factor
+   * of R.
+   */
+  if (redmode == 0)
+    (res.*redux)(m, mp);
+
+  swap(res);
+}
+
+
+
+template<class A, class T>
+inline mp_int<A,T> pow(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n)
+{
+  mp_int<A,T> tmp(x);
+  tmp.pow(n);
+  return tmp;
+}
+
+template<class A, class T>
+inline mp_int<A,T> modpow(const mp_int<A,T>& base,
+                          const mp_int<A,T>& exp,
+                          const mp_int<A,T>& mod)
+{
+  mp_int<A,T> tmp(base);
+  tmp.modpow(exp, mod);
+  return tmp;
+}
+
+
+
+
Added: sandbox/mp_math/boost/mp_math/mp_int/prime.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/prime.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,334 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// this one simply divides x by some small primes found in prime_tab
+// returns false if definitely composite, returns true if probably prime
+// this test is to be used to quickly filter out composite numbers
+// for example testing for 2,5,7 will eliminate 54% of all odd numbers
+// testing for all primes less than 100 eliminates 70%, for all primes
+// less than 256 it is 80%.
+struct primality_division_test
+{
+  typedef bool result_type;
+
+  template<class A, class T>
+  bool operator()(const mp_int<A,T>& p) const;
+};
+
+
+template<class A, class T>
+bool primality_division_test::operator()(const mp_int<A,T>& p) const
+{
+  typedef typename mp_int<A,T>::traits_type traits;
+  typedef typename traits::digit_type       digit_type;
+  typedef detail::prime_tab<digit_type>     prime_tab;
+
+  if (p.is_even())
+  {
+    if (p != digit_type(2))
+      return false;
+    else
+      return true;
+  }
+
+  mp_int<A,T> tmp;
+  for (int i = 0; i < prime_tab::num_primes; ++i)
+  {
+    /* what is x mod prime_tab[i] */
+    tmp = p;
+    const digit_type r =
+      tmp.divide_by_digit(
+          static_cast<digit_type>(prime_tab::values[i]));
+
+    /* is the residue zero? */
+    if (r == 0)
+    {
+      if (p != prime_tab::values[i])
+        return false;
+      else
+        return true; // definitely prime
+    }
+  }
+  return true;
+}
+
+
+
+// fermat primality test:
+// If an integer p is a prime number, then for all integers a,
+// dividing both a p and a by p gives a result with the same remainder.
+//
+// if p is in fact prime then a**p = a (mod p)
+// for all 0 < a < p
+// or alternatively: a**(p-1) = 1 (mod p)
+//
+// returns true if p is probably prime
+// NOTE: may return true for carmichael numbers
+template<
+  class Distribution = uniform_mp_int<>
+>
+class primality_fermat_test
+{
+  const unsigned int rounds_;
+  
+public:
+
+  typedef Distribution distribution_type;
+  typedef bool         result_type;
+
+  explicit primality_fermat_test(unsigned int rounds)
+  :
+    rounds_(rounds)
+  {}
+
+  template<class Engine, class A, class T>
+  bool operator()(Engine& e, const mp_int<A,T>& p) const;
+};
+
+
+template<class Distribution>
+template<class Engine, class A, class T>
+bool
+primality_fermat_test<Distribution>::operator()
+  (Engine& eng, const mp_int<A,T>& p) const
+{
+  typedef typename mp_int<A,T>::digit_type digit_type;
+  
+  const digit_type one = 1;
+  const mp_int<A,T> p1(p-one);
+  
+  distribution_type rng(digit_type(2), p1);
+  
+  for (unsigned int i = 0; i < rounds_; ++i)
+  {
+    mp_int<A,T> base = rng(eng);
+
+    base.set_least_significant_bit(); // test only odd bases
+    
+    const mp_int<A,T> tmp = modpow(base, p1, p);
+
+    if (tmp != one)
+      return false; // definitely composite!
+  }
+  
+  return true;
+}
+
+
+// Miller-Rabin test
+// This is an improved version of the Fermat test that will also detect
+// carmichael numbers.
+// The probability that a composite number is reported as prime
+// is less than 1/(4**k) where k is the number of rounds
+template<
+  class Distribution = uniform_mp_int<>
+>
+class primality_miller_rabin_test
+{
+  const unsigned int rounds_;
+
+  static const struct rtable
+  {
+    unsigned k, t;
+  } sizes_[];
+
+public:
+
+  typedef Distribution distribution_type;
+  typedef bool         result_type;
+
+  explicit primality_miller_rabin_test(unsigned int rounds = 0)
+  :
+    rounds_(rounds)
+  {}
+
+  // p must be odd
+  template<class Engine, class A, class T>
+  bool operator()(Engine& e, const mp_int<A,T>& p) const;
+
+  // return the recommended number of rounds for numbers of size 'bits'
+  // so that the probability of error is lower than 2^-96
+  static unsigned int recommended_number_of_rounds(unsigned bits);
+};
+
+// This table comes from libtommath, HAC has one too but with slightly lower
+// numbers of rounds.
+template<class Distribution>
+const typename primality_miller_rabin_test<Distribution>::rtable
+primality_miller_rabin_test<Distribution>::sizes_[] =
+{
+  {   128,    28 },
+  {   256,    16 },
+  {   384,    10 },
+  {   512,     7 },
+  {   640,     6 },
+  {   768,     5 },
+  {   896,     4 },
+  {  1024,     4 }
+};
+
+
+template<class Distribution>
+template<class Engine, class A, class T>
+bool
+primality_miller_rabin_test<Distribution>::operator()
+  (Engine& eng, const mp_int<A,T>& p) const
+{
+  assert(p.is_odd());
+
+  unsigned int r;
+  if (rounds_)
+    r = rounds_;
+  else
+    r = recommended_number_of_rounds(p.precision());
+  
+  mp_int<A,T> n = abs(p);
+  --n;
+
+  const typename mp_int<A,T>::size_type s = n.count_lsb();
+  n >>= s; // p-1 / 2**s
+
+  const typename mp_int<A,T>::digit_type one = 1;
+  const mp_int<A,T> p_minus_one(p-one);
+  distribution_type rng(one, p_minus_one);
+  
+  for (unsigned int i = 0; i < r; ++i)
+  {
+    const mp_int<A,T> base = rng(eng);
+    mp_int<A,T> y = modpow(base,n,p);
+    
+    for (typename mp_int<A,T>::size_type j = 0; j < s; ++j)
+    {
+      const bool b = (y != one) && (y != p_minus_one);
+      y.sqr();
+      y %= p;
+      if (b && (y == one))
+        return false;
+    }
+    if (y != one)
+      return false;
+  }
+  return true;
+}
+
+template<class Distribution>
+unsigned int
+primality_miller_rabin_test<Distribution>::recommended_number_of_rounds(
+                                                                  unsigned bits)
+{
+  int i;
+
+  for (i = 0; i < 8; ++i)
+  {
+    if (sizes_[i].k == bits)
+      return sizes_[i].t;
+    else if (sizes_[i].k > bits)
+      return (i == 0) ? sizes_[0].t : sizes_[i - 1].t;
+  }
+
+  return sizes_[i-1].t + 1;
+}
+
+
+
+
+template<class A, class T, class PrimalityTest>
+inline bool is_prime(const mp_int<A,T>& x, PrimalityTest f = PrimalityTest())
+{
+  return f(x);
+}
+
+
+template<
+  class PrimalityTest,
+  class Dist = uniform_mp_int_bits<>
+>
+struct prime_generator
+{
+  typedef PrimalityTest              primality_test;
+  typedef Dist                       distribution_type;
+  typedef typename Dist::result_type result_type;
+
+  explicit prime_generator(std::size_t bits,
+                           PrimalityTest test = PrimalityTest())
+  :
+    bits_(bits),
+    test_(test)
+  {}
+
+  template<class Engine>
+  result_type operator()(Engine& e) const;
+
+  std::size_t bits_;
+  const primality_test test_;
+};
+
+template<class PrimalityTest, class Dist>
+template<class Engine>
+typename Dist::result_type
+prime_generator<PrimalityTest,Dist>::operator()(Engine& eng) const
+{
+  distribution_type dist(bits_);
+  result_type candidate;
+  do
+  {
+    candidate = dist(eng);
+    candidate.set_least_significant_bit(); // make odd
+  } while (!is_prime(candidate, test_));
+
+  return candidate;
+}
+
+
+// A prime p is called safe if (p-1)/2 is also prime
+template<
+  class PrimalityTest,
+  class Dist = uniform_mp_int_bits<>
+>
+struct safe_prime_generator
+{
+  typedef PrimalityTest              primality_test;
+  typedef Dist                       distribution_type;
+  typedef typename Dist::result_type result_type;
+
+  explicit safe_prime_generator(std::size_t bits,
+                                PrimalityTest test = PrimalityTest())
+  :
+    bits_(bits),
+    test_(test)
+  {}
+
+  template<class Engine>
+  result_type operator()(Engine& e) const;
+
+  std::size_t bits_;
+  const primality_test test_;
+};
+
+
+template<class PrimalityTest, class Dist>
+template<class Engine>
+typename Dist::result_type
+safe_prime_generator<PrimalityTest,Dist>::operator()(Engine& eng) const
+{
+  prime_generator<PrimalityTest, Dist> prime_gen(bits_-1, test_);
+  result_type p;
+  do
+  {
+    do
+    {
+      p = prime_gen(eng);
+      p.multiply_by_2();
+      ++p;
+    } while (!is_prime(p, test_));
+  } while (p.precision() > bits_); // catch extremely rare case
+
+  return p;
+}
+
+
+
+
+
Added: sandbox/mp_math/boost/mp_math/mp_int/random.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/random.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,185 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/*#ifndef BOOST_MP_MATH_MP_INT_RANDOM_HPP
+#define BOOST_MP_MATH_MP_INT_RANDOM_HPP
+
+namespace boost {
+namespace mp_math {
+
+template<class A, class T>
+struct mp_int;
+
+*/
+
+// this class is modeled after boost::uniform_int
+// in fact it uses boost::uniform_int internally
+template<class MpInt = mp_int<> >
+struct uniform_mp_int
+{
+  typedef MpInt input_type;
+  typedef MpInt result_type;
+
+  // is min() and max() known at compile time?
+  static const bool has_fixed_range = false;
+
+  uniform_mp_int(const MpInt& min, const MpInt& max)
+  :
+    min_(min),
+    max_(max),
+    d_(0, MpInt::digit_max)
+  {}
+
+  result_type min() const { return min_; }
+  result_type max() const { return max_; }
+
+  void reset() { d_.reset(); }
+  
+  template<class Engine>
+  result_type operator()(Engine& e);
+  
+private:
+
+  MpInt min_, max_;
+  uniform_int<typename MpInt::digit_type> d_;
+};
+
+template<class MpInt>
+const bool uniform_mp_int<MpInt>::has_fixed_range;
+
+
+template<class MpInt>
+template<class Engine>
+typename uniform_mp_int<MpInt>::result_type
+uniform_mp_int<MpInt>::operator()(Engine& e)
+{
+  result_type tmp;
+  tmp.grow_capacity(max_.size());
+    
+  for (typename result_type::size_type i = 0; i < max_.size(); ++i)
+    tmp[i] = d_(e);
+    
+  tmp.set_size(max_.size());
+  tmp.clamp();
+    
+  if (tmp > max_)
+    tmp %= max_;
+
+  return tmp;
+}
+
+
+template<class MpInt = mp_int<> >
+struct uniform_mp_int_bits
+{
+  typedef MpInt input_type;
+  typedef MpInt result_type;
+
+  static const bool has_fixed_range = false;
+
+  explicit uniform_mp_int_bits(typename MpInt::size_type bits)
+  :
+    d_(0, MpInt::digit_max),
+    bits_(bits)
+  {}
+
+  result_type min() const;
+  result_type max() const;
+
+  typename MpInt::size_type precision() const { return bits_; }
+
+  void reset() { d_.reset(); }
+  
+  template<class Engine>
+  result_type operator()(Engine& e);
+  
+private:
+
+  uniform_int<typename MpInt::digit_type> d_;
+  typename MpInt::size_type bits_;
+};
+
+template<class MpInt>
+const bool uniform_mp_int_bits<MpInt>::has_fixed_range;
+
+
+template<class MpInt>
+template<class Engine>
+typename uniform_mp_int_bits<MpInt>::result_type
+uniform_mp_int_bits<MpInt>::operator()(Engine& e)
+{
+  result_type tmp;
+
+  const typename MpInt::size_type offset = bits_ / MpInt::valid_bits + 1;
+
+  tmp.grow_capacity(offset);
+
+  for (typename result_type::size_type i = 0; i < offset; ++i)
+    tmp[i] = d_(e);
+  
+  tmp.set_size(offset);
+
+  const typename MpInt::digit_type mask =
+      (~typename MpInt::digit_type(0))
+    << (bits_ % MpInt::valid_bits);
+
+  tmp[offset-1] &= ~mask;
+  
+  tmp.set_bit(bits_-1); // make exactly bits_ bits long
+  
+  return tmp;
+}
+
+template<class MpInt>
+typename uniform_mp_int_bits<MpInt>::result_type
+uniform_mp_int_bits<MpInt>::min() const
+{
+  result_type tmp;
+  
+  const typename MpInt::size_type offset =
+    bits_ / MpInt::valid_bits + 1;
+  
+  tmp.grow_capacity(offset);
+  
+  std::memset(tmp.digits(), 0,
+      offset * sizeof(typename MpInt::digit_type));
+  
+  tmp.set_size(offset);
+  tmp.set_bit(bits_ - 1);
+  
+  return tmp;
+}
+
+template<class MpInt>
+typename uniform_mp_int_bits<MpInt>::result_type
+uniform_mp_int_bits<MpInt>::max() const
+{
+  result_type tmp;
+  const typename MpInt::size_type offset =
+    bits_ / MpInt::valid_bits + 1;
+  
+  tmp.grow_capacity(offset);
+  
+  for (typename result_type::size_type i = 0; i < offset; ++i)
+    tmp[i] = MpInt::digit_max;
+  
+  tmp.set_size(offset);
+
+  const typename MpInt::digit_type mask =
+      (~typename MpInt::digit_type(0))
+    << (bits_ % MpInt::valid_bits);
+
+  tmp[offset-1] &= ~mask;
+
+  return tmp;
+}
+
+
+/*
+} // namespace boost
+} // namespace mp_math
+
+#endif
+*/
Added: sandbox/mp_math/boost/mp_math/mp_int/root.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/root.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,116 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+template<class A, class T>
+mp_int<A,T> sqrt(const mp_int<A,T>& x)
+{
+  /* must be positive */
+  if (x.sign() == -1)
+    throw std::domain_error("sqrt: argument is negative");
+
+  mp_int<A,T> t1;
+
+  /* easy out */
+  if (x.is_zero())
+  {
+    t1.zero();
+    return t1;
+  }
+
+  t1 = x;
+
+  /* First approx. (not very bad for large arg) */
+  t1.shift_digits_right(t1.size()/2);
+
+  /* t1 > 0  */ 
+  mp_int<A,T> t2 = x / t1;
+
+  t1 += t2;
+  t1.divide_by_2();
+  /* And now t1 > sqrt(arg) */
+  do
+  {
+    t2 = x / t1;
+    t1 += t2;
+    t1.divide_by_2();
+    /* t1 >= sqrt(arg) >= t2 at this point */
+  } while (t1.compare_magnitude(t2) == 1);
+
+  return t1;
+}
+
+
+/* find the n'th root of an integer 
+ *
+ * Result found such that (c)**b <= a and (c+1)**b > a 
+ *
+ * This algorithm uses Newton's approximation 
+ * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
+ * which will find the root in log(N) time where 
+ * each step involves a fair bit.  This is not meant to 
+ * find huge roots [square and cube, etc].
+ */
+template<class A, class T>
+mp_int<A,T> nth_root(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n)
+{
+  mp_int<A,T> t1, t2, t3;
+
+  /* input must be positive if n is even */
+  if ((n & 1) == 0 && x.is_negative())
+    throw std::domain_error("nth_root: argument must be positive if n is even");
+
+  /* if x is negative fudge the sign but keep track */
+  const int neg = x.sign();
+  const_cast<mp_int<A,T>*>(&x)->set_sign(1);
+
+  /* t2 = 2 */
+  t2 = typename mp_int<A,T>::digit_type(2);
+
+  do
+  {
+    t1 = t2;
+
+    /* t2 = t1 - ((t1**n - x) / (n * t1**(n-1))) */
+    
+    /* t3 = t1**(n-1) */
+    t3 = pow(t1, n-1);
+
+    /* numerator */
+    /* t2 = t1**n */
+    t2 = t3 * t1;
+
+    /* t2 = t1**n - x */
+    t2 -= x;
+
+    /* denominator */
+    /* t3 = t1**(n-1) * n  */
+    t3.multiply_by_digit(n);
+
+    /* t3 = (t1**n - x)/(n * t1**(n-1)) */
+    t3 = t2 / t3;
+
+    t2 = t1 - t3;
+  } while (t1 != t2);
+  
+  /* result can be off by a few so check */
+  for (;;)
+  {
+    t2 = pow(t1, n);
+
+    if (t2 > x)
+      t1.sub_digit(1);
+    else
+      break;
+  }
+
+  /* reset the sign of x first */
+  const_cast<mp_int<A,T>*>(&x)->set_sign(neg);
+
+  /* set the sign of the result */
+  t1.set_sign(neg);
+
+  return t1;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,200 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* squaring using Toom-Cook 3-way algorithm */
+template<class A, class T>
+void mp_int<A,T>::toom_sqr()
+{
+  mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+
+  const size_type B = used_ / 3;
+
+  /* a = a2 * B**2 + a1 * B + a0 */
+  a0 = *this;
+  a0.modulo_2_to_the_power_of(valid_bits * B);
+
+  a1 = *this;
+  a1.shift_digits_right(B);
+  a1.modulo_2_to_the_power_of(valid_bits * B);
+
+  a2 = *this;
+  a2.shift_digits_right(B * 2);
+
+  /* w0 = a0*a0 */
+  w0 = a0;
+  w0.sqr();
+
+  /* w4 = a2 * a2 */
+  w4 = a2;
+  w4.sqr();
+
+  /* w1 = (a2 + 2(a1 + 2a0))**2 */
+  w1 = a0;
+  w1.multiply_by_2();
+  w1 += a1;
+  w1.multiply_by_2();
+  w1 += a2;
+  w1.sqr();
+
+  /* w3 = (a0 + 2(a1 + 2a2))**2 */
+  w3 = a2;
+  w3.multiply_by_2();
+  w3 += a1;
+  w3.multiply_by_2();
+  w3 += a0;
+  w3.sqr();
+
+  /* w2 = (a2 + a1 + a0)**2 */
+  w2 = a1 + a2;
+  w2 += a0;
+  w2.sqr();
+
+  /* now solve the matrix
+
+     0  0  0  0  1
+     1  2  4  8  16
+     1  1  1  1  1
+     16 8  4  2  1
+     1  0  0  0  0
+
+     using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+   */
+
+  /* r1 - r4 */
+  w1 -= w4;
+  /* r3 - r0 */
+  w3 -= w0;
+  /* r1/2 */
+  w1.divide_by_2();
+  /* r3/2 */
+  w3.divide_by_2();
+  /* r2 - r0 - r4 */
+  w2 -= w0;
+  w2 -= w4;
+  /* r1 - r2 */
+  w1 -= w2;
+  /* r3 - r2 */
+  w3 -= w2;
+  /* r1 - 8r0 */
+  tmp1 = w0;
+  tmp1 <<= 3;
+  w1 -= tmp1;
+  /* r3 - 8r4 */
+  tmp1 = w4;
+  tmp1 <<= 3;
+  w3 -= tmp1;
+  /* 3r2 - r1 - r3 */
+  w2.multiply_by_digit(3);
+  w2 -= w1;
+  w2 -= w3;
+  /* r1 - r2 */
+  w1 -= w2;
+  /* r3 - r2 */
+  w3 -= w2;
+  /* r1/3 */
+  w1.divide_by_3();
+  /* r3/3 */
+  w3.divide_by_3();
+  /* at this point shift W[n] by B*n */
+  w1.shift_digits_left(1 * B);
+  w2.shift_digits_left(2 * B);
+  w3.shift_digits_left(3 * B);
+  w4.shift_digits_left(4 * B);
+  *this = w0 + w1;
+  tmp1 = w2 + w3;
+  tmp1 += w4;
+  *this += tmp1;
+}
+
+/* Karatsuba squaring, computes b = a*a using three 
+ * half size squarings
+ *
+ * See comments of karatsuba_mul for details.  It 
+ * is essentially the same algorithm but merely 
+ * tuned to perform recursive squarings.
+ */
+// a    = x1 * B**n + x0
+// a**2 = x1x1 * B**2n + 2*x0x1 * B**n + x0x0
+// where
+// 2*x0x1 = 1) x1x1 + x0x0 - (x1 - x0)**2   or
+//          2) (x0 + x1)**2 - (x0x0 + x1x1)
+// we use version 1)
+// version 2) may use one less temporary?
+// a**2 = x1x1 * B**2n + (x1x1 + x0x0 - (x1 - x0)**2) * B**n + x0x0
+// TODO revert!
+template<class A, class T>
+void mp_int<A,T>::karatsuba_sqr()
+{
+  mp_int x0, x1, tmp, tmp2, x0x0, x1x1;
+
+  /* min # of digits divided in two */
+  const size_type B = used_ >> 1;
+
+  /* init copy all the temps */
+  x0.grow_capacity(B);
+  x1.grow_capacity(used_ - B);
+
+  /* init temps */
+  x0x0.grow_capacity(B * 2);
+  x1x1.grow_capacity((used_ - B) * 2);
+
+  /* now shift the digits */
+  std::memcpy(x0.digits_, digits_, B * sizeof(digit_type));
+  std::memcpy(x1.digits_, digits_ + B, (used_ - B) * sizeof(digit_type));
+
+  x0.used_ = B;
+  x1.used_ = used_ - B;
+
+  x0.clamp();
+
+  x0x0 = x0;
+  x0x0.sqr();
+  x1x1 = x1;
+  x1x1.sqr();
+
+  tmp = x1x1;
+  tmp.add_magnitude(x0x0);
+
+  tmp2 = x1;
+  tmp2 -= x0;
+  tmp2.sqr();
+
+  tmp.sub_smaller_magnitude(tmp2);
+
+  x1x1.shift_digits_left(B * 2);
+  tmp.shift_digits_left(B);
+
+  x1x1.add_magnitude(tmp);
+  x1x1.add_magnitude(x0x0);
+  swap(x1x1);
+}
+
+template<class A, class T>
+void mp_int<A,T>::comba_sqr()
+{
+  mp_int tmp;
+  tmp.grow_capacity(used_ + used_);
+
+  ops_type::comba_sqr(tmp.digits(), digits(), used_);
+
+  tmp.used_ = used_ + used_;
+  
+  tmp.clamp();
+  swap(tmp);
+}
+
+// computes *this = *this * *this
+template<class A, class T>
+void mp_int<A,T>::sqr()
+{
+  if (used_ >= traits_type::toom_sqr_cutoff)
+    toom_sqr();
+  else if (used_ >= traits_type::karatsuba_sqr_cutoff)
+    karatsuba_sqr();
+  else
+    comba_sqr();
+  sign_ = 1;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,309 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace detail
+{
+  template<typename charT>
+  inline int ascii_to_value(const charT c)
+  {
+    switch (c)
+    {
+      case '0': case '1': case '2': case '3': case '4':
+      case '5': case '6': case '7': case '8': case '9':
+        return c - '0';
+      case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+        return c - 'A' + 10;
+      case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+        return c - 'a' + 10;
+    }
+    return c;
+  }
+}
+
+// low level from string conversion routine
+// Requires:
+// - used_ = 0
+// - first and last must point into string without sign prefix and without base
+//   prefix (like 0x)
+// - radix is 8, 10 or 16
+template<class A, class T>
+template<typename Iter>
+void mp_int<A,T>::from_string(Iter first, Iter last, unsigned radix)
+{
+  assert(used_ == 0);
+  assert(first != last);
+
+  const detail::string_conversion_constants<mp_int> sc(radix);
+
+  const size_type length = std::distance(first, last);
+
+  static const char* inv_msg = "mp_int<>::from_string: invalid character";
+  
+  const bool is_power_of_two = (radix & (radix - 1)) == 0;
+  if (is_power_of_two)
+  {
+    const size_type required =
+      (length * sc.radix_storage_bits + (valid_bits - 1)) / valid_bits;
+    grow_capacity(required);
+
+    digit_type result = 0;
+    int        offset = 0;
+    
+    typedef std::reverse_iterator<Iter> reverse_iter_type;
+    for (reverse_iter_type c(last); c != reverse_iter_type(first); ++c)
+    {
+      const digit_type x = static_cast<digit_type>(detail::ascii_to_value(*c));
+      
+      if (x >= radix)
+        throw std::invalid_argument(inv_msg);
+      
+      result |= x << offset;
+      offset += sc.radix_storage_bits;
+      
+      if (offset >= valid_bits)
+      {
+        digits_[used_++] = result;
+        offset -= valid_bits;
+        result = static_cast<digit_type>(x >> (sc.radix_storage_bits - offset));
+      }
+    }
+    
+    if (result || !used_)
+      digits_[used_++] = result;
+    
+    clamp();
+    if (is_zero())
+      sign_ = 1;
+  }
+  else // radix can only be 10 at this point
+  {
+    size_type required;
+    // approximate log2(10) with 10/3
+    if (length < std::numeric_limits<size_type>::max()/10U)
+      required = (10U * length + 2U) / 3U;
+    else
+      required = length / 3U * 10U;
+    required = (required + (valid_bits - 1)) / valid_bits;
+    
+    grow_capacity(required);
+
+    for (size_type i = sc.max_power; i < length; i += sc.max_power)
+    {
+      digit_type result = 0U;
+
+      // first convert a block of decimal digits to radix 10^sc.max_power
+      // which will still fit into a digit_type
+      for (unsigned int j = 0; j < sc.max_power; ++j)
+      {
+        const digit_type x = *first++ - '0';
+        if (x >= 10U)
+          throw std::invalid_argument(inv_msg);
+        result = result * 10U + x;
+      }
+
+      // then use multi precision routines to convert this digit to binary
+      if (used_)
+      {
+        digit_type carry = ops_type::multiply_by_digit(digits_, digits_, used_,
+                                                            sc.max_power_value);
+
+        carry += ops_type::add_single_digit(digits_, digits_, used_, result);
+        
+        if (carry)
+          digits_[used_++] = carry;
+      }
+      else
+        digits_[used_++] = result;
+    }
+
+    // one last round for the remaining decimal digits
+    if (first != last)
+    {
+      word_type radix_power = 1U;
+      digit_type result = 0U;
+      
+      while (first != last)
+      {
+        const digit_type x = *first++ - '0';
+        if (x >= 10U)
+          throw std::invalid_argument(inv_msg);
+        result = result * 10U + x;
+        radix_power *= 10U;
+      }
+      
+      if (used_)
+      {
+        digit_type carry = ops_type::multiply_by_digit(digits_, digits_, used_,
+                                          static_cast<digit_type>(radix_power));
+
+        carry += ops_type::add_single_digit(digits_, digits_, used_, result);
+
+        if (carry)
+          digits_[used_++] = carry;
+      }
+      else
+        digits_[used_++] = result;
+    }
+  }
+}
+
+
+namespace detail
+{
+  template<typename T, class Alloc>
+  struct scoped_ptr : Alloc
+  {
+    T* ptr;
+    std::size_t size;
+    explicit scoped_ptr(std::size_t s) : size(s) { ptr = this->allocate(size); }
+    ~scoped_ptr() { this->deallocate(ptr,size); }
+  };
+}
+
+
+// TODO use an output iterator then we can easily output to different string
+// types. But keep a high level to_string function to allocate string memory
+// only once.
+template<class A, class T>
+template<class StringT>
+StringT mp_int<A,T>::to_string(std::ios_base::fmtflags f) const
+{
+  typedef typename StringT::value_type char_type;
+
+  StringT s;
+
+  if (!used_)
+    return s;
+
+  digit_type radix;
+
+  if (f & std::ios_base::hex)
+    radix = 16;
+  else if (f & std::ios_base::oct)
+    radix = 8;
+  else if (f & std::ios_base::dec)
+    radix = 10;
+  else
+    throw std::invalid_argument("mp_int<>::to_string: unsupported radix");
+
+  char_type prefix[3];
+  char_type* p = prefix;
+
+  if (is_negative())
+    *p++ = '-';
+  else if (f & std::ios_base::showpos)
+    *p++ = '+';
+
+  if (f & std::ios_base::showbase)
+  {
+    if (radix == 16)
+    {
+      *p++ = '0';
+      if (f & std::ios_base::uppercase)
+        *p++ = 'X';
+      else
+        *p++ = 'x';
+    }
+    else if (radix == 8)
+      *p++ = '0';
+  }
+
+  const int prefix_offset = p - prefix;
+
+  if (is_zero())
+  {
+    s.reserve(prefix_offset + 1);
+    for (int i = 0; i < prefix_offset; ++i)
+      s.push_back(prefix[i]);
+    if (!(f & std::ios_base::oct))
+      s.push_back('0');
+    return s;
+  }
+
+  const detail::string_conversion_constants<mp_int> sc(radix);
+  const bool is_power_of_two = (radix & (radix - 1)) == 0;
+
+  size_type total_bits = precision();
+  // round up to a multiple of sc.radix_storage_bits
+  if (total_bits % sc.radix_storage_bits)
+    total_bits = total_bits - total_bits % sc.radix_storage_bits
+               + sc.radix_storage_bits;
+  
+  size_type required;
+  if (is_power_of_two)
+    required = (total_bits + (sc.radix_storage_bits - 1))
+             / sc.radix_storage_bits;
+  // approximate log2(10) with 13/4
+  else if (total_bits < std::numeric_limits<size_type>::max() / 4)
+    required = (total_bits * 4 + 12) / 13;
+  else
+    required = total_bits / 13 * 4;
+
+  required += prefix_offset;
+  detail::scoped_ptr<char_type, typename StringT::allocator_type> sd(required);
+
+  char_type* c = sd.ptr;
+  
+  for (int i = 0; i < prefix_offset; ++i)
+    *c++ = prefix[i];
+
+  if (is_power_of_two)
+  {
+    static const char* const lowercase_tab = "0123456789abcdef";
+    static const char* const uppercase_tab = "0123456789ABCDEF";
+
+    const char* const tab = (f & std::ios_base::uppercase)
+                          ? uppercase_tab
+                          : lowercase_tab;
+    
+    const digit_type mask = (1 << sc.radix_storage_bits) - 1;
+
+    int offset = total_bits % valid_bits;
+    if (!offset)
+      offset = valid_bits;
+    
+    const_reverse_iterator d = rbegin();
+    for (;;)
+    {
+      offset -= sc.radix_storage_bits;
+      while (offset >= 0)
+      {
+        *c++ = tab[(*d >> offset) & mask];
+        offset -= sc.radix_storage_bits;
+      }
+      const digit_type partial_value = (*d << -offset) & mask;
+      if (++d == rend())
+        break;
+      offset += valid_bits;
+      *c++ = tab[partial_value | (*d >> offset)];
+    }
+  }
+  else
+  {
+    digit_type m = 2;
+    for (digit_type i = 100; i < sc.max_power_value; i *= 10)
+      ++m;
+    
+    mp_int tmp = abs(*this);
+    
+    while (!tmp.is_zero())
+    {
+      digit_type remainder = tmp.divide_by_digit(sc.max_power_value);
+      
+      for (digit_type i = 0; i < m; ++i)
+      {
+        if (remainder || !tmp.is_zero())
+          *c++ = '0' + remainder % 10U;
+        remainder /= 10U;
+      }
+    }
+    std::reverse(sd.ptr + prefix_offset, c);
+  }
+
+  s.assign(sd.ptr, c);
+
+  return s;
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/sub.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/sub.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,43 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+template<class A, class T>
+void mp_int<A,T>::sub_digit(digit_type b)
+{
+  if (is_negative())
+  {
+    sign_ = 1;
+    add_digit(b);
+    sign_ = -1;
+    return;
+  }
+
+  if (used_ == 1)
+  {
+    if (digits_[0] < b) // example: 2 - 6 = -4
+    {
+      digits_[0] = b - digits_[0];
+      sign_ = -1;
+    }
+    else // example 8 - 7 = 1 or 5 - 5 = 0
+      digits_[0] -= b;
+  }
+  else
+  {
+    ops_type::subtract_single_digit(digits_, digits_, used_, b);
+    if (!digits_[used_-1])
+      --used_;
+  }
+}
+
+// low level subtraction (assumes |*this| >= |rhs|), HAC pp.595 Algorithm 14.9
+template<class A, class T>
+inline void mp_int<A,T>::sub_smaller_magnitude(const mp_int& rhs)
+{
+  ops_type::sub_smaller_magnitude(digits_, digits_, used_, rhs.digits_, rhs.used_);
+
+  clamp();
+}
+
Added: sandbox/mp_math/boost/mp_math/mp_int/traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/mp_int/traits.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,98 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_MP_INT_TRAITS_HPP
+#define BOOST_MP_MATH_MP_INT_TRAITS_HPP
+
+#include <cstddef> // size_t
+#include <boost/config.hpp>
+#include <boost/mpl/back.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/lower_bound.hpp>
+#include <boost/mpl/vector.hpp>
+
+
+namespace boost {
+namespace mp_math {
+
+namespace detail {
+
+typedef mpl::vector<
+  unsigned char,
+  unsigned short,
+  unsigned int,
+  unsigned long int
+  #ifdef BOOST_HAS_LONG_LONG
+  ,
+  unsigned long long int
+  #endif
+> unsigned_type_vec;
+
+template<typename T1, typename T2>
+struct cmp_digits
+:
+mpl::bool_<
+  std::numeric_limits<T1>::digits < std::numeric_limits<T2>::digits/2
+>
+{
+};
+
+// we could also choose unsigned int (since this is propably the
+// fastest unsigned integer type) as digit_type then
+// try to find a larger type as word_type
+// if none exists set unsigned int as word_type and choose next
+// smaller type as digit_type
+struct choose
+{
+  typedef mpl::back<unsigned_type_vec>::type word_type;
+  typedef mpl::deref<
+      mpl::lower_bound<
+        unsigned_type_vec, word_type, cmp_digits<mpl::_1,mpl::_2>
+        >::type
+      >::type digit_type;
+};
+
+} // namespace detail
+
+
+template<
+  typename Digit = detail::choose::digit_type,
+  typename Word = detail::choose::word_type/*,
+  bool debug = false*/
+>
+struct mp_int_traits
+{
+  BOOST_STATIC_ASSERT(
+    std::numeric_limits<Digit>::digits <= std::numeric_limits<Word>::digits/2
+  );
+
+  typedef std::size_t size_type; // TODO should prolly get size_type from allocator_type
+  typedef Digit       digit_type;
+  typedef Word        word_type;
+
+  static size_type toom_mul_cutoff;
+  static size_type toom_sqr_cutoff;
+  static size_type karatsuba_mul_cutoff;
+  static size_type karatsuba_sqr_cutoff;
+};
+
+
+#define BMPINT_init(S) template<typename D, typename W>\
+  typename mp_int_traits<D,W>::S mp_int_traits<D,W>::
+BMPINT_init(size_type  )toom_mul_cutoff = 350;
+BMPINT_init(size_type  )toom_sqr_cutoff = 400;
+BMPINT_init(size_type  )karatsuba_mul_cutoff = 80;
+BMPINT_init(size_type  )karatsuba_sqr_cutoff = 120;
+
+#undef BMPINT_init
+
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif
+
Added: sandbox/mp_math/libs/mp_math/doc/bibliography.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/bibliography.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,21 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section Bibliography]
+
+[heading GMP (GNU Multiple Precision Arithmetic Library)]
+* [@http://gmplib.org/]
+
+[heading Handbook of Applied Cryptogtaphy]
+* [@http://www.cacr.math.uwaterloo.ca/hac/]
+
+[heading libtommath]
+* [@http://libtom.org/] `// this link seems to be down lately (10/26/2008)`
+* [@http://math.libtomcrypt.com/] `// this works but is out of date`
+
+[heading Miller-Rabin Primality Test]
+* [@http://www.bitnuts.de/rienhardt/docs/miller_rabin.pdf]
+
+[endsect][/Bibliography]
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/add.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/ctor_dec.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/ctor_hex.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/divide.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/input_vecs.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/modpow.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/modulo.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/multiply.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/square.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/subtract.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/to_dec.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/benchmark_imgs/k7/to_hex.png
==============================================================================
Binary file. No diff available.
Added: sandbox/mp_math/libs/mp_math/doc/html/boostbook.css
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/boostbook.css	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,519 @@
+/*=============================================================================
+    Copyright (c) 2004 Joel de Guzman
+    http://spirit.sourceforge.net/
+
+    Distributed under the Boost Software License, Version 1.0. (See accompany-
+    ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+/*=============================================================================
+    Body defaults
+=============================================================================*/
+
+    body 
+    {
+        margin: 1em;
+        font-family: sans-serif;
+    }
+
+/*=============================================================================
+    Paragraphs
+=============================================================================*/
+
+    p 
+    {
+        text-align: left;
+        font-size: 10pt; 
+        line-height: 1.15;
+    }
+
+/*=============================================================================
+    Program listings
+=============================================================================*/
+
+    /* Code on paragraphs */
+    p tt.computeroutput
+    {
+        font-size: 9pt;
+    }
+
+    pre.synopsis
+    {
+        font-size: 90%;
+        margin: 1pc 4% 0pc 4%;
+        padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+    }
+
+    .programlisting, 
+    .screen
+    {
+        font-size: 9pt;
+        display: block;
+        margin: 1pc 4% 0pc 4%;
+        padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+    }
+
+    /* Program listings in tables don't get borders */
+    td .programlisting, 
+    td .screen
+    {
+        margin: 0pc 0pc 0pc 0pc;
+        padding:  0pc 0pc 0pc 0pc;
+    }
+
+/*=============================================================================
+    Headings
+=============================================================================*/
+
+    h1, h2, h3, h4, h5, h6 
+    { 
+        text-align: left; 
+        margin: 1em 0em 0.5em 0em;
+        font-weight: bold;
+    }
+
+    h1 { font: 140% }
+    h2 { font: bold 140% }
+    h3 { font: bold 130% }
+    h4 { font: bold 120% }
+    h5 { font: italic 110% }
+    h6 { font: italic 100% }
+
+    /* Top page titles */
+    title, 
+    h1.title, 
+    h2.title
+    h3.title, 
+    h4.title, 
+    h5.title, 
+    h6.title, 
+    .refentrytitle
+    {
+        font-weight: bold;
+        margin-bottom: 1pc;
+    }
+
+    h1.title { font-size: 140% }
+    h2.title { font-size: 140% }
+    h3.title { font-size: 130% }
+    h4.title { font-size: 120% }
+    h5.title { font-size: 110% }
+    h6.title { font-size: 100% }
+
+    .section h1 
+    {
+        margin: 0em 0em 0.5em 0em;
+        font-size: 140%;
+    }
+
+    .section h2 { font-size: 140% }
+    .section h3 { font-size: 130% }
+    .section h4 { font-size: 120% }
+    .section h5 { font-size: 110% }
+    .section h6 { font-size: 100% }
+
+    /* Code on titles */
+    h1 tt.computeroutput { font-size: 140% }
+    h2 tt.computeroutput { font-size: 140% }
+    h3 tt.computeroutput { font-size: 130% }
+    h4 tt.computeroutput { font-size: 120% }
+    h5 tt.computeroutput { font-size: 110% }
+    h6 tt.computeroutput { font-size: 100% }
+
+/*=============================================================================
+    Author
+=============================================================================*/
+
+    h3.author 
+    { 
+        font-size: 100% 
+    }
+
+/*=============================================================================
+    Lists
+=============================================================================*/
+
+    li
+    {
+        font-size: 10pt;
+        line-height: 1.3;
+    }
+    
+    /* Unordered lists */
+    ul 
+    {
+        text-align: left;
+    }
+    
+    /* Ordered lists */
+    ol 
+    {
+        text-align: left;
+    }
+
+/*=============================================================================
+    Links
+=============================================================================*/
+
+    a
+    {
+        text-decoration: none; /* no underline */
+    }
+    
+    a:hover
+    {
+        text-decoration: underline;
+    }
+
+/*=============================================================================
+    Spirit style navigation
+=============================================================================*/
+
+    .spirit-nav
+    {
+        text-align: right;
+    }
+    
+    .spirit-nav a
+    {
+        color: white;
+        padding-left: 0.5em;
+    }
+    
+    .spirit-nav img
+    {
+        border-width: 0px;
+    }
+
+/*=============================================================================
+    Table of contents
+=============================================================================*/
+
+    .toc
+    {
+       margin: 1pc 4% 0pc 4%;
+       padding: 0.1pc 1pc 0.1pc 1pc;
+       font-size: 80%; 
+       line-height: 1.15;
+    }
+    
+    .boost-toc
+    {
+       float: right;
+       padding: 0.5pc;
+    }
+
+/*=============================================================================
+    Tables
+=============================================================================*/
+
+    .table-title, 
+    div.table p.title
+    {
+        margin-left: 4%;
+        padding-right: 0.5em; 
+        padding-left: 0.5em;
+    }
+    
+    .informaltable table, 
+    .table table
+    {
+        width: 92%;
+        margin-left: 4%;
+        margin-right: 4%;
+    }
+    
+    div.informaltable table, 
+    div.table table
+    {
+        padding: 4px;
+    }
+    
+    /* Table Cells */
+    div.informaltable table tr td, 
+    div.table table tr td
+    {
+        padding: 0.5em;
+        text-align: left;
+        font-size: 9pt;
+    }
+
+    div.informaltable table tr th, 
+    div.table table tr th
+    {
+        padding: 0.5em 0.5em 0.5em 0.5em;
+        border: 1pt solid white;
+        font-size: 80%;
+    }
+
+/*=============================================================================
+    Blurbs
+=============================================================================*/
+
+    div.note,
+    div.tip,
+    div.important,
+    div.caution,
+    div.warning,
+    p.blurb
+    {
+        font-size: 9pt; /* A little bit smaller than the main text */
+        line-height: 1.2;
+        display: block;
+        margin: 1pc 4% 0pc 4%;
+        padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+    }
+    
+    p.blurb img
+    {
+        padding: 1pt;
+    }
+
+/*=============================================================================
+    Variable Lists
+=============================================================================*/
+
+    /* Make the terms in definition lists bold */
+    div.variablelist dl dt,
+    span.term
+    {
+        font-weight: bold;
+        font-size: 10pt;
+    }
+
+    div.variablelist table tbody tr td
+    {
+        text-align: left;
+        vertical-align: top;
+        padding: 0em 2em 0em 0em;
+        font-size: 10pt;
+        margin: 0em 0em 0.5em 0em;
+        line-height: 1;
+    }
+
+    div.variablelist dl dt
+    {
+        margin-bottom: 0.2em;
+    }
+
+    div.variablelist dl dd
+    {
+        margin: 0em 0em 0.5em 2em;
+        font-size: 10pt;
+    }
+
+    div.variablelist table tbody tr td p,
+    div.variablelist dl dd p
+    {
+        margin: 0em 0em 0.5em 0em;
+        line-height: 1;
+    }
+
+/*=============================================================================
+    Misc
+=============================================================================*/
+
+    /* Title of books and articles in bibliographies */
+    span.title
+    {
+        font-style: italic;
+    }
+
+    span.underline
+    {
+        text-decoration: underline;
+    }
+
+    span.strikethrough
+    {
+        text-decoration: line-through;
+    }
+
+    /* Copyright, Legal Notice */
+    div div.legalnotice p
+    {
+        text-align: left
+    }
+
+/*=============================================================================
+    Colors
+=============================================================================*/
+
+    @media screen
+    {
+    /* Links */
+        a
+        {
+            color: #005a9c;
+        }
+    
+        a:visited
+        {
+            color: #9c5a9c;
+        }
+
+        h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
+        h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
+        h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
+        {
+            text-decoration: none; /* no underline */
+            color: #000000;
+        }
+    
+    /* Syntax Highlighting */
+        .keyword        { color: #0000AA; }
+        .identifier     { color: #000000; }
+        .special        { color: #707070; }
+        .preprocessor   { color: #402080; }
+        .char           { color: teal; }
+        .comment        { color: #800000; }
+        .string         { color: teal; }
+        .number         { color: teal; }
+        .white_bkd      { background-color: #FFFFFF; }
+        .dk_grey_bkd    { background-color: #999999; }
+    
+    /* Copyright, Legal Notice */
+        .copyright      
+        { 
+            color: #666666; 
+            font-size: small; 
+        }
+    
+        div div.legalnotice p
+        {
+            color: #666666;
+        }
+    
+    /* Program listing */
+        pre.synopsis
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+        .programlisting, 
+        .screen
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+        td .programlisting, 
+        td .screen
+        {
+            border: 0px solid #DCDCDC;
+        }
+    
+    /* Blurbs */
+        div.note,
+        div.tip,
+        div.important,
+        div.caution,
+        div.warning,
+        p.blurb
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+    /* Table of contents */
+        .toc
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+    /* Tables */
+        div.informaltable table tr td, 
+        div.table table tr td
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+        div.informaltable table tr th, 
+        div.table table tr th
+        {
+            background-color: #F0F0F0;
+            border: 1px solid #DCDCDC;
+        }
+    
+    /* Misc */
+        span.highlight
+        {
+            color: #00A000;
+        }
+    }
+    
+    @media print
+    {
+    /* Links */
+        a
+        {
+            color: black;
+        }
+    
+        a:visited
+        {
+            color: black;
+        }
+    
+        .spirit-nav
+        {
+            display: none;
+        }
+    
+    /* Program listing */
+        pre.synopsis
+        {
+            border: 1px solid gray;
+        }
+    
+        .programlisting, 
+        .screen
+        {
+            border: 1px solid gray;
+        }
+    
+        td .programlisting, 
+        td .screen
+        {
+            border: 0px solid #DCDCDC;
+        }
+    
+    /* Table of contents */
+        .toc
+        {
+            border: 1px solid gray;
+        }
+    
+        .informaltable table, 
+        .table table
+        {
+            border: 1px solid gray;
+            border-collapse: collapse;
+        }
+    
+    /* Tables */
+        div.informaltable table tr td, 
+        div.table table tr td
+        {
+            border: 1px solid gray;
+        }
+    
+        div.informaltable table tr th, 
+        div.table table tr th
+        {
+            border: 1px solid gray;
+        }
+    
+    /* Misc */
+        span.highlight
+        {
+            font-weight: bold;
+        }
+    }
+
+/*=============================================================================
+    Images
+=============================================================================*/
+
+    span.inlinemediaobject img
+    {
+        vertical-align: middle;
+    }
\ No newline at end of file
Added: sandbox/mp_math/libs/mp_math/doc/html/index.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/index.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,109 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 1. mp_int</title>
+<link rel="stylesheet" href="boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="index.html" title="Chapter 1. mp_int">
+<link rel="next" href="mp_int_/tutorial.html" title="Tutorial">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="mp_int_/tutorial.html"><img src="../../../../doc/html/images/next.png" alt="Next"></a></div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div>
+<div><h2 class="title">
+<a name="mp_int"></a>Chapter 1. mp_int </h2></div>
+<div><div class="author"><h3 class="author">
+<span class="firstname">Kevin</span> <span class="surname">Sopp</span>
+</h3></div></div>
+<div><p class="copyright">Copyright © 2008 Kevin Sopp</p></div>
+<div><div class="legalnotice">
+<a name="id2693145"></a><p>
+        All code and documentation is in the public domain
+      </p>
+</div></div>
+</div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="section">Introduction</span></dt>
+<dt><span class="section">Tutorial</span></dt>
+<dd><dl>
+<dt><span class="section">General use</span></dt>
+<dt><span class="section"><a href="mp_int_/tutorial.html#mp_int_.tutorial.random_number_generation">Random number
+      generation</a></span></dt>
+<dt><span class="section">Primality testing</span></dt>
+<dt><span class="section"><a href="mp_int_/tutorial.html#mp_int_.tutorial.prime_number_generation">Prime number
+      generation</a></span></dt>
+</dl></dd>
+<dt><span class="section">Performance</span></dt>
+<dd><dl>
+<dt><span class="section">Tips</span></dt>
+<dt><span class="section">Measurements</span></dt>
+</dl></dd>
+<dt><span class="section">Implementation notes</span></dt>
+<dd><dl>
+<dt><span class="section"><a href="mp_int_/implementation_notes.html#mp_int_.implementation_notes.mp_int_structure">mp_int
+      structure</a></span></dt>
+<dt><span class="section">Semantics</span></dt>
+</dl></dd>
+<dt><span class="section">mp_int reference</span></dt>
+<dt><span class="section">mp_int_traits reference</span></dt>
+<dt><span class="section">uniform_mp_int reference</span></dt>
+<dt><span class="section"><a href="mp_int_/uniform_mp_int_bits_reference.html">uniform_mp_int_bits
+    reference</a></span></dt>
+<dt><span class="section">Primality Tests reference</span></dt>
+<dd><dl>
+<dt><span class="section">primality_division_test</span></dt>
+<dt><span class="section">primality_fermat_test</span></dt>
+<dt><span class="section">primality_miller_rabin_test</span></dt>
+</dl></dd>
+<dt><span class="section">Bibliography</span></dt>
+</dl>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.introduction"></a><a class="link" href="index.html#mp_int_.introduction" title="Introduction">Introduction</a>
+</h2></div></div></div>
+<p>
+      This library provides the <code class="computeroutput"><span class="identifier">mp_int</span></code>
+      class template for arbitrary precision signed integers. These integers grow
+      dynamically as needed. Additionally, special functions which are necessary
+      for the implementation of public key cryptography such as prime generation
+      are provided.
+    </p>
+<a name="mp_int_.introduction.acknowledgement"></a><h4>
+<a name="id2733685"></a>
+      <a class="link" href="index.html#mp_int_.introduction.acknowledgement">Acknowledgement</a>
+    </h4>
+<p>
+      This library originally started as a port of the C code of libtommath. Without
+      the huge amount of work done by its author Tom St. Denis, this library wouldn't
+      have been possible. Not only does he provide free C code, but also a very detailed
+      pdf document of over 200 pages explaining the algorithms used in his code.
+      Both his documentation and his code were placed in the public domain. In the
+      spirit of his work the code of the <code class="computeroutput"><span class="identifier">mp_int</span></code>
+      library and its documentation are placed in the <span class="bold"><strong>public
+      domain</strong></span> as well.
+    </p>
+</div>
+<p>
+  </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"><p><small>Last revised: October 06, 2008 at 11:40:14 GMT</small></p></td>
+<td align="right"><div class="copyright-footer"></div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="mp_int_/tutorial.html"><img src="../../../../doc/html/images/next.png" alt="Next"></a></div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/bibliography.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/bibliography.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,71 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Bibliography</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="primality_tests_reference.html" title="Primality Tests reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="primality_tests_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.bibliography"></a><a class="link" href="bibliography.html" title="Bibliography">Bibliography</a>
+</h2></div></div></div>
+<a name="mp_int_.bibliography.gmp__gnu_multiple_precision_arithmetic_library_"></a><h4>
+<a name="id2791749"></a>
+      <a class="link" href="bibliography.html#mp_int_.bibliography.gmp__gnu_multiple_precision_arithmetic_library_">GMP
+      (GNU Multiple Precision Arithmetic Library)</a>
+    </h4>
+<div class="itemizedlist"><ul type="disc"><li>http://gmplib.org/</li></ul></div>
+<a name="mp_int_.bibliography.handbook_of_applied_cryptogtaphy"></a><h4>
+<a name="id2791785"></a>
+      <a class="link" href="bibliography.html#mp_int_.bibliography.handbook_of_applied_cryptogtaphy">Handbook
+      of Applied Cryptogtaphy</a>
+    </h4>
+<div class="itemizedlist"><ul type="disc"><li>http://www.cacr.math.uwaterloo.ca/hac/</li></ul></div>
+<a name="mp_int_.bibliography.libtommath"></a><h4>
+<a name="id2791820"></a>
+      <a class="link" href="bibliography.html#mp_int_.bibliography.libtommath">libtommath</a>
+    </h4>
+<div class="itemizedlist"><ul type="disc">
+<li>
+http://libtom.org/<code class="computeroutput"><span class="comment">// this link seems to be down lately (10/26/2008)</span></code>
+</li>
+<li>
+http://math.libtomcrypt.com/<code class="computeroutput"><span class="comment">// this works but is out of date</span></code>
+</li>
+</ul></div>
+<a name="mp_int_.bibliography.miller_rabin_primality_test"></a><h4>
+<a name="id2791886"></a>
+      <a class="link" href="bibliography.html#mp_int_.bibliography.miller_rabin_primality_test">Miller-Rabin
+      Primality Test</a>
+    </h4>
+<div class="itemizedlist"><ul type="disc"><li>http://www.bitnuts.de/rienhardt/docs/miller_rabin.pdf</li></ul></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="primality_tests_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/implementation_notes.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/implementation_notes.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,98 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Implementation notes</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="performance.html" title="Performance">
+<link rel="next" href="mp_int_reference.html" title="mp_int reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="performance.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="mp_int_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.implementation_notes"></a><a class="link" href="implementation_notes.html" title="Implementation notes">Implementation notes</a>
+</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section"><a href="implementation_notes.html#mp_int_.implementation_notes.mp_int_structure">mp_int
+      structure</a></span></dt>
+<dt><span class="section">Semantics</span></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.implementation_notes.mp_int_structure"></a><a class="link" href="implementation_notes.html#mp_int_.implementation_notes.mp_int_structure" title="mp_int structure">mp_int
+      structure</a>
+</h3></div></div></div>
+<p>
+        An <code class="computeroutput"><span class="identifier">mp_int</span></code> is handled in a
+        sign plus magnitude representation which looks like this:
+      </p>
+<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">mp_int</span>
+<span class="special">{</span>
+  <span class="identifier">digit_type</span><span class="special">*</span> <span class="identifier">digits_</span><span class="special">;</span>
+  <span class="identifier">size_type</span> <span class="identifier">used_</span><span class="special">,</span> <span class="identifier">capacity_</span><span class="special">;</span>
+  <span class="keyword">int</span> <span class="identifier">sign_</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<p>
+        The least significant digit of the number always lives at <code class="computeroutput"><span class="identifier">digits_</span><span class="special">[</span><span class="number">0</span><span class="special">]</span></code>
+        while the most significant lives at <code class="computeroutput"><span class="identifier">digits_</span><span class="special">[</span><span class="identifier">used_</span> <span class="special">-</span> <span class="number">1</span><span class="special">]</span></code>.
+      </p>
+<p>
+        Libtommath on which this code is ultimately based chose a <code class="computeroutput"><span class="identifier">digit_type</span></code>
+        representation which does not use all of its bits, instead some bits are
+        reserved to hold carries in intermediate results. This allows very fast multiplication
+        routines. I chose a different representation which uses all the bits in the
+        <code class="computeroutput"><span class="identifier">digit_type</span></code> but needs explicit
+        carry handling in the code. This makes normal c++ code a tad slower. However
+        it makes it much easier to write assembler routines since most CPUs provide
+        instructions that allow the handling of carries in place. This is what GMP
+        does as well. It is possible that a <code class="computeroutput"><span class="identifier">digit_type</span></code>
+        representation similar to libtommath's returns someday which can then be
+        enabled via a different <code class="computeroutput"><span class="identifier">mp_int_traits</span></code>
+        class template.
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.implementation_notes.semantics"></a><a class="link" href="implementation_notes.html#mp_int_.implementation_notes.semantics" title="Semantics">Semantics</a>
+</h3></div></div></div>
+<div class="itemizedlist"><ul type="disc">
+<li>
+          An integer with a value of zero has a <code class="computeroutput"><span class="identifier">used_</span></code>
+          count of 1 and <code class="computeroutput"><span class="identifier">digits_</span><span class="special">[</span><span class="number">0</span><span class="special">]</span></code>
+          holds the value 0.
+        </li>
+<li>
+          An unitialized integer has no value and all operations on it except for
+          initializing or swapping are undefined.
+        </li>
+</ul></div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="performance.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="mp_int_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/mp_int_reference.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/mp_int_reference.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,2123 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>mp_int reference</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="implementation_notes.html" title="Implementation notes">
+<link rel="next" href="mp_int_traits_reference.html" title="mp_int_traits reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="implementation_notes.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="mp_int_traits_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.mp_int_reference"></a><a class="link" href="mp_int_reference.html" title="mp_int reference">mp_int reference</a>
+</h2></div></div></div>
+<a name="mp_int_.mp_int_reference.synopsis"></a><h4>
+<a name="id2745751"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.synopsis">Synopsis</a>
+    </h4>
+<pre class="programlisting"><span class="comment">// <boost/mp_math/mp_int.hpp>
+</span><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span>
+<span class="keyword">namespace</span> <span class="identifier">mp_math</span> <span class="special">{</span>
+
+<span class="keyword">template</span><span class="special"><</span>
+  <span class="keyword">class</span> <span class="identifier">Allocator</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span><span class="keyword">void</span><span class="special">>,</span>
+  <span class="keyword">class</span> <span class="identifier">Traits</span> <span class="special">=</span> <span class="identifier">mp_int_traits</span><span class="special"><></span>
+<span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">mp_int</span>
+<span class="special">{</span>
+  <span class="keyword">typedef</span> <span class="identifier">Allocator</span> <span class="identifier">allocator_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="identifier">Traits</span>    <span class="identifier">traits_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">size_type</span><span class="special">;</span>
+
+  <span class="comment">// ctor/cctor/dtor/assign
+</span>  <span class="identifier">mp_int</span><span class="special">();</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">enable_if</span><span class="special"><</span><span class="identifier">is_integral</span><span class="special"><</span><span class="identifier">IntegralT</span><span class="special">></span> <span class="special">>::</span><span class="identifier">type</span><span class="special">*</span> <span class="identifier">dummy</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span>
+  
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RandomAccessIterator</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">RandomAccessIterator</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">RandomAccessIterator</span> <span class="identifier">last</span><span class="special">);</span>
+  
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+  
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RandomAccessIterator</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">RandomAccessIterator</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">RandomAccessIterator</span> <span class="identifier">last</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">copy</span><span class="special">);</span>
+
+  <span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_HAS_RVALUE_REFS</span>
+  <span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special">&&</span> <span class="identifier">copy</span><span class="special">);</span>
+  <span class="preprocessor">#endif</span>
+  
+  <span class="special">~</span><span class="identifier">mp_int</span><span class="special">();</span>
+
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
+
+  <span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_HAS_RVALUE_REFS</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">mp_int</span><span class="special">&&</span> <span class="identifier">rhs</span><span class="special">);</span>
+  <span class="preprocessor">#endif</span>
+  
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">rhs</span><span class="special">);</span>
+
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+
+  <span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+
+  <span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>  
+  
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RandomAccessIterator</span><span class="special">></span>
+  <span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="identifier">RandomAccessIterator</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">RandomAccessIterator</span> <span class="identifier">last</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+
+  <span class="comment">// modifiers
+</span>  <span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_HAS_RVALUE_REFS</span>
+  <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special">&&</span> <span class="identifier">other</span><span class="special">);</span>
+  <span class="preprocessor">#else</span>
+  <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">other</span><span class="special">);</span>
+  <span class="preprocessor">#endif</span>
+
+  <span class="comment">// increment/decrement
+</span>  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">++();</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">--();</span>
+  <span class="identifier">mp_int</span>  <span class="keyword">operator</span> <span class="special">++(</span><span class="keyword">int</span><span class="special">);</span>
+  <span class="identifier">mp_int</span>  <span class="keyword">operator</span> <span class="special">--(</span><span class="keyword">int</span><span class="special">);</span>
+
+  <span class="comment">// shifting
+</span>  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special"><<=</span> <span class="special">(</span><span class="identifier">size_type</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">>>=</span> <span class="special">(</span><span class="identifier">size_type</span><span class="special">);</span>
+
+  <span class="comment">// unary negate
+</span>  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-</span> <span class="special">();</span>
+
+  <span class="comment">// arithmetic operators
+</span>  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+
+  <span class="comment">// bitwise operators
+</span>  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+
+  <span class="comment">// operators involving integral types
+</span>  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+
+  <span class="comment">// operators involving char strings
+</span>  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+
+  <span class="comment">// operators involving wchar_t strings
+</span>  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+
+  <span class="comment">// operators involving std::basic_string
+</span>  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+  <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+
+  <span class="comment">// observers
+</span>  <span class="identifier">allocator_type</span> <span class="identifier">get_allocator</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="keyword">bool</span> <span class="identifier">is_even</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+  <span class="keyword">bool</span> <span class="identifier">is_odd</span> <span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="keyword">bool</span> <span class="identifier">is_positive</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+  <span class="keyword">bool</span> <span class="identifier">is_negative</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="identifier">size_type</span> <span class="identifier">precision</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="keyword">operator</span> <span class="identifier">unspecified_bool_type</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">to_string</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">dec</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+  <span class="identifier">IntegralT</span> <span class="identifier">to_integral</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="comment">// low level access
+</span>  <span class="keyword">typedef</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">digit_type</span> <span class="identifier">digit_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">word_type</span>  <span class="identifier">word_type</span><span class="special">;</span>
+
+  <span class="keyword">bool</span> <span class="identifier">is_zero</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="identifier">digit_type</span><span class="special">&</span>       <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">size_type</span> <span class="identifier">i</span><span class="special">);</span>
+  <span class="keyword">const</span> <span class="identifier">digit_type</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">size_type</span> <span class="identifier">i</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+  
+  <span class="identifier">digit_type</span><span class="special">&</span>       <span class="identifier">at</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">i</span><span class="special">);</span>
+  <span class="keyword">const</span> <span class="identifier">digit_type</span><span class="special">&</span> <span class="identifier">at</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">i</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+<span class="special">};</span>
+
+
+<span class="comment">// non-member functions
+</span>
+<span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_HAS_RVALUE_REFS</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&&,</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&&);</span>
+<span class="preprocessor">#else</span>
+<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+<span class="preprocessor">#endif</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special"><<</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">size_type</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">>></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">size_type</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">+</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">-</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">*</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">/</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">%</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">|</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">&</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">^</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">+</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">-</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">*</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">/</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">%</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">|</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">&</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">^</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+
+<span class="comment">// Comparison operators
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="comment">// Comparison between mp_int and std::basic_string
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="comment">// Comparison between std::basic_string and mp_int
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="comment">// Comparison between mp_int and const char*
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="comment">// Comparison between const char* and mp_int
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="comment">// Comparison between mp_int and const wchar_t*
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="comment">// Comparison between const wchar_t* and mp_int
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="comment">// Comparison between mp_int and integral type
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="comment">// Comparison between integral type and mp_int
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+
+<span class="comment">// Stream I/O
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">></span>
+<span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span>
+<span class="keyword">operator</span> <span class="special">>></span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span> <span class="identifier">is</span><span class="special">,</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">></span>
+<span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span>
+<span class="keyword">operator</span> <span class="special"><<</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span> <span class="identifier">os</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">);</span>
+
+
+<span class="comment">// Special functions
+</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">abs</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">gcd</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">b</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">lcm</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">b</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">int</span> <span class="identifier">jacobi</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">pow</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">digit_type</span> <span class="identifier">n</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">modpow</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">base</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">exp</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span
><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">mod</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">sqrt</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">nth_root</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">digit_type</span> <span class="identifier">n</span><span class="special">);</span>
+
+
+<span class="special">}</span> <span class="comment">// namespace mp_math
+</span><span class="special">}</span> <span class="comment">// namespace boost
+</span></pre>
+<a name="mp_int_.mp_int_reference.construction_from___assignment_to_a_string_object"></a><h4>
+<a name="id2762818"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.construction_from___assignment_to_a_string_object">Construction
+      from / assignment to a string object</a>
+    </h4>
+<p>
+      In a constructor or assignment operation without the possibility to specify
+      the base of the string argument the base of the number is deduced from the
+      string. If the string starts with <code class="computeroutput"><span class="number">0</span><span class="identifier">x</span></code> or <code class="computeroutput"><span class="number">0</span><span class="identifier">X</span></code> then the number will be treated as hexadecimal
+      value. If the string starts with <code class="computeroutput"><span class="number">0</span></code>
+      then the number will be treated as octal value else it will be treated as decimal
+      value. An optional <code class="computeroutput"><span class="special">-</span></code> sign is allowed
+      as the first character in the string to indicate a negative value.
+    </p>
+<p>
+      In a constructor or assignment operation with the ability to specify the format
+      of the string argument via a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span></code>
+      parameter, possible formatting flags are:
+    </p>
+<div class="itemizedlist"><ul type="disc">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">showbase</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">dec</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">hex</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">oct</span></code></li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.construct_copy_destroy_assign"></a><h4>
+<a name="id2763067"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.construct_copy_destroy_assign">Construct/Copy/Destroy/Assign</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">();</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an empty <code class="computeroutput"><span class="identifier">mp_int</span></code> object, such an uninitialized <code class="computeroutput"><span class="identifier">mp_int</span></code> has no value, i.e. it is <span class="emphasis"><em>not</em></span>
+        zero.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">enable_if</span><span class="special"><</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_integral</span><span class="special"><</span><span class="identifier">IntegralT</span><span class="special">></span> <span class="special">>::</span><span class="identifier">type</span><span class="special">*</span> <span class="identifier">dummy</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from an integral type. The value of the object is that of the integral
+        type.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N) where N is the number of
+        bits of IntegralT.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        points to a valid number formatted as string or to an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from a string.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        contains a valid number formatted as string or <code class="computeroutput"><span class="identifier">s</span></code>
+        is an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from a string.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RandomAccessIterator</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">RandomAccessIterator</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">RandomAccessIterator</span> <span class="identifier">last</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">first</span></code>
+        and <code class="computeroutput"><span class="identifier">last</span></code> are iterators into
+        a string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from two iterators.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        points to a valid number formatted according to the flags in <code class="computeroutput"><span class="identifier">f</span></code> or <code class="computeroutput"><span class="identifier">s</span></code>
+        is an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from a string.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character or if an unrecognized formatting flag was set.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        contains a valid number formatted according to the flags in <code class="computeroutput"><span class="identifier">f</span></code> or <code class="computeroutput"><span class="identifier">s</span></code>
+        is an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from a string.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character or if an unrecognized formatting flag was set.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RandomAccessIterator</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">RandomAccessIterator</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">RandomAccessIterator</span> <span class="identifier">last</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">first</span></code>
+        and <code class="computeroutput"><span class="identifier">last</span></code> are iterators into
+        a string formatted according to the formatting flags in <code class="computeroutput"><span class="identifier">f</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from two iterators.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character or if an unrecognized formatting flag was set.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">copy</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs a copy of a given <code class="computeroutput"><span class="identifier">mp_int</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N), where N is the number
+        of digits in <code class="computeroutput"><span class="identifier">copy</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special">&&</span> <span class="identifier">copy</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        by moving <code class="computeroutput"><span class="identifier">copy</span></code> into <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="special">~</span><span class="identifier">mp_int</span><span class="special">();</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Destroys <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Copies the value of <code class="computeroutput"><span class="identifier">rhs</span></code> into <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">mp_int</span><span class="special">&&</span> <span class="identifier">rhs</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> obtains the value of <code class="computeroutput"><span class="identifier">rhs</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">rhs</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> obtains the value of <code class="computeroutput"><span class="identifier">rhs</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> basic.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        points to a valid number formatted as string or to an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span> <span class="special">=</span> <span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">s</span><span class="special">);</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> basic.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        points to a valid number formatted as string or to an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span> <span class="special">=</span> <span class="identifier">mp_int</span><span class="special">(</span><span class="identifier">s</span><span class="special">);</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> basic.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+<span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        points to a valid number formatted according to the flags in <code class="computeroutput"><span class="identifier">f</span></code> or <code class="computeroutput"><span class="identifier">s</span></code>
+        is an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from a string.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character or if an unrecognized formatting flag was set.
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> basic.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>  
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">s</span></code>
+        contains a valid number formatted according to the flags in <code class="computeroutput"><span class="identifier">f</span></code> or <code class="computeroutput"><span class="identifier">s</span></code>
+        is an empty string.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from a string.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character or if an unrecognized formatting flag was set.
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> basic.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RandomAccessIterator</span><span class="special">></span>
+<span class="keyword">void</span> <span class="identifier">assign</span><span class="special">(</span><span class="identifier">RandomAccessIterator</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">RandomAccessIterator</span> <span class="identifier">last</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">first</span></code>
+        and <code class="computeroutput"><span class="identifier">last</span></code> are iterators into
+        a string formatted according to the formatting flags in <code class="computeroutput"><span class="identifier">f</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs an <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        object from two iterators.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character or if an unrecognized formatting flag was set.
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> basic.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.modifiers"></a><h4>
+<a name="id2766915"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.modifiers">Modifiers</a>
+    </h4>
+<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special">&&</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Swaps the value of <code class="computeroutput"><span class="identifier">other</span></code> and <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> nothrow.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">other</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Swaps the value of <code class="computeroutput"><span class="identifier">other</span></code> and <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> nothrow.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.increment_decrement"></a><h4>
+<a name="id2767133"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.increment_decrement">Increment/decrement</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">++();</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span><pre class="programlisting"><span class="special">*</span><span class="keyword">this</span> <span class="special">+=</span> <span class="number">1</span><span class="special">;</span>
+<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
+</pre>
+</li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> best case is O(1), worst case
+        is O(N) - this happens when the addition causes a carry bit to ripple through
+        all digits subsequently.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">--();</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span><pre class="programlisting"><span class="special">*</span><span class="keyword">this</span> <span class="special">-=</span> <span class="number">1</span><span class="special">;</span>
+<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
+</pre>
+</li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> best case is O(1), worst case
+        is O(N) - this happens when the subtraction causes a borrow bit to ripple
+        through all digits subsequently.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span>  <span class="keyword">operator</span> <span class="special">++(</span><span class="keyword">int</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span><pre class="programlisting"><span class="identifier">mp_int</span> <span class="identifier">tmp</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span>
+<span class="special">*</span><span class="keyword">this</span> <span class="special">+=</span> <span class="number">1</span><span class="special">;</span>
+<span class="keyword">return</span> <span class="identifier">tmp</span><span class="special">;</span>
+</pre>
+</li>
+<li>
+<span class="bold"><strong>Returns:</strong></span> The value of <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> before incrementation.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span>  <span class="keyword">operator</span> <span class="special">--(</span><span class="keyword">int</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span><pre class="programlisting"><span class="identifier">mp_int</span> <span class="identifier">tmp</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span>
+<span class="special">*</span><span class="keyword">this</span> <span class="special">-=</span> <span class="number">1</span><span class="special">;</span>
+<span class="keyword">return</span> <span class="identifier">tmp</span><span class="special">;</span>
+</pre>
+</li>
+<li>
+<span class="bold"><strong>Returns:</strong></span> The value of <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> before decrementation.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.shifting"></a><h4>
+<a name="id2767861"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.shifting">Shifting</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special"><<=</span> <span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Shift <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by <code class="computeroutput"><span class="identifier">x</span></code>
+        bits to the left.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">>>=</span> <span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Shift <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by <code class="computeroutput"><span class="identifier">x</span></code>
+        bits to the right.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.unary_negate"></a><h4>
+<a name="id2768196"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.unary_negate">Unary negate</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-</span> <span class="special">();</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Negates <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> nothrow.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.arithmetic_operators"></a><h4>
+<a name="id2768321"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.arithmetic_operators">Arithmetic operators</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Adds <code class="computeroutput"><span class="identifier">x</span></code>
+        to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Subtracts <code class="computeroutput"><span class="identifier">x</span></code>
+        from <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Multiplies <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> If <code class="computeroutput"><span class="special">&</span><span class="identifier">x</span> <span class="special">==</span> <span class="keyword">this</span></code>
+        then a squaring algorithm will be used. Different multiplication algorithms
+        are chosen for numbers of different size. The thresholds can be tuned via
+        the <code class="computeroutput"><span class="identifier">mp_int_traits</span></code> class template
+        parameter.
+        <div class="itemizedlist"><ul type="circle">
+<li>
+            Small numbers: Comba algorithm O(N^2).
+          </li>
+<li>
+            Midsize numbers: Karatsuba algorithm O(N^log2(3)) ~ O(N^1.585).
+          </li>
+<li>
+            Large numbers: Toom-Cook algorithm O(N^(log(5)/log(3))) ~ O(N^1.465).
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">x</span>
+        <span class="special">!=</span> <span class="number">0</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Divides <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span></code> if <code class="computeroutput"><span class="identifier">x</span>
+            <span class="special">==</span> <span class="number">0</span></code>.
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">x</span>
+        <span class="special">!=</span> <span class="number">0</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Modulus <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span></code> if <code class="computeroutput"><span class="identifier">x</span>
+            <span class="special">==</span> <span class="number">0</span></code>.
+          </li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.bitwise_operators"></a><h4>
+<a name="id2769381"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.bitwise_operators">Bitwise operators</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> OR <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> AND <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> XOR <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.operators_involving_integral_types"></a><h4>
+<a name="id2769904"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.operators_involving_integral_types">Operators
+      involving integral types</a>
+    </h4>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Adds <code class="computeroutput"><span class="identifier">x</span></code>
+        to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Subtracts <code class="computeroutput"><span class="identifier">x</span></code>
+        to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Multiplies <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Divides <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> modulo <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Applies the bitwise or operation
+        on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+        and the absolute of <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Applies the bitwise and operation
+        on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+        and the absolute of <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span> <span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="identifier">IntegralT</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Applies the bitwise xor operation
+        on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
+        and the absolute of <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.operators_involving_char_wchar_t_strings"></a><h4>
+<a name="id2771318"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.operators_involving_char_wchar_t_strings">Operators
+      involving char/wchar_t strings</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*</span> <span class="identifier">s</span><span class="special">);</span>
+</pre>
+<a name="mp_int_.mp_int_reference.operators_involving_std__basic_string"></a><h4>
+<a name="id2772175"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.operators_involving_std__basic_string">Operators
+      involving std::basic_string</a>
+    </h4>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">+=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">-=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">/=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">%=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">|=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">&=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">^=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&</span> <span class="identifier">s</span><span class="special">);</span>
+</pre>
+<a name="mp_int_.mp_int_reference.observers"></a><h4>
+<a name="id2773367"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.observers">Observers</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">allocator_type</span> <span class="identifier">get_allocator</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns: </strong></span> A copy of the allocator.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing if allocator copy constructor
+        is nothrow.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">is_even</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">is_odd</span> <span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">is_positive</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">is_negative</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">size_type</span> <span class="identifier">precision</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The number of bits used by the
+        absolute value of *this.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(N).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">operator</span> <span class="identifier">unspecified_bool_type</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span> <span class="special">!=</span> <span class="number">0</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">to_string</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span> <span class="identifier">f</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">dec</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> to a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
+        formatting of the string is done according to the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">fmtflags</span></code>
+        parameter. Possible formatting flags are:
+        <div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">showpos</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">showbase</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">dec</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">hex</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">oct</span></code></li>
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">uppercase</span></code></li>
+</ul></div>
+</li>
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> converted to a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
+        object.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">IntegralT</span> <span class="identifier">to_integral</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> converted to an object of type <code class="computeroutput"><span class="identifier">IntegralT</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">overflow_error</span></code>
+        if <code class="computeroutput"><span class="identifier">IntegralT</span></code> does not have
+        enough precision to hold the result.
+      </li>
+<li>
+<span class="bold"><strong>Exception safety:</strong></span> strong.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.non_member_functions"></a><h4>
+<a name="id2774432"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.non_member_functions">Non-member functions</a>
+    </h4>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&&,</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special"><<</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">size_type</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">>></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">size_type</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">+</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">-</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">*</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">/</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">%</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">|</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">&</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">^</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">+</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">-</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">*</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">/</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">%</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">|</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">&</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">operator</span> <span class="special">^</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+</pre>
+<p>
+      These functions are implemented in terms of their respective member functions.
+    </p>
+<a name="mp_int_.mp_int_reference.comparison_operators"></a><h4>
+<a name="id2777278"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.comparison_operators">Comparison operators</a>
+    </h4>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> These operators compare the numeric
+        value of their arguments and return a truth value based on that evaluation.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span> Nothing.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the string argument to
+        an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the left side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Traits</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Alloc</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span><span class="identifier">Traits</span><span class="special">,</span><span class="identifier">Alloc</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the string argument to
+        an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the right side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the string argument to
+        an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the left side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the string argument to
+        an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the right side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the string argument to
+        an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the left side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="keyword">wchar_t</span><span class="special">*,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the string argument to
+        an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the right side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">invalid_argument</span></code> if the string contains
+            an invalid character.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&,</span> <span class="identifier">IntegralT</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the integral argument
+        to an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the left side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">IntegralT</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span><span class="identifier">IntegralT</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Effects:</strong></span> Converts the integral argument
+        to an <code class="computeroutput"><span class="identifier">mp_int</span></code> object and compares
+        it to the object on the right side of the expression.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<a name="mp_int_.mp_int_reference.stream_i_o"></a><h4>
+<a name="id2785287"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.stream_i_o">Stream I/O</a>
+    </h4>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">></span>
+<span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span>
+<span class="keyword">operator</span> <span class="special">>></span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span> <span class="identifier">is</span><span class="special">,</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">);</span>
+
+<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span><span class="special">></span>
+<span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span>
+<span class="keyword">operator</span> <span class="special"><<</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special"><</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">>&</span> <span class="identifier">os</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<a name="mp_int_.mp_int_reference.special_functions"></a><h4>
+<a name="id2785746"></a>
+      <a class="link" href="mp_int_reference.html#mp_int_.mp_int_reference.special_functions">Special functions</a>
+    </h4>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">abs</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The positive value of <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(1).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">gcd</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">b</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The greatest common divisor of
+        <code class="computeroutput"><span class="identifier">a</span></code> and <code class="computeroutput"><span class="identifier">b</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O((log2(AB))^2).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">lcm</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">b</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The least common multiple of <code class="computeroutput"><span class="identifier">a</span></code> and <code class="computeroutput"><span class="identifier">b</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O((log2(AB))^2).
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">int</span> <span class="identifier">jacobi</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The Jacobi symbol of integer <code class="computeroutput"><span class="identifier">a</span></code> and positive odd integer <code class="computeroutput"><span class="identifier">p</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span></code> if <code class="computeroutput"><span class="identifier">p</span></code>
+            is negative.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">pow</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">digit_type</span> <span class="identifier">n</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The <code class="computeroutput"><span class="identifier">n</span></code>th
+        power of <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">modpow</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">base</span><span class="special">,</span>
+                   <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">exp</span><span class="special">,</span>
+                   <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">mod</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns: </strong></span><code class="computeroutput"><span class="special">(</span><span class="identifier">base</span> <span class="special">^</span> <span class="identifier">exp</span><span class="special">)</span> <span class="special">%</span>
+        <span class="identifier">mod</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws: </strong></span><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">sqrt</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The square root of <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span></code> if <code class="computeroutput"><span class="identifier">x</span></code>
+            is negative.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">nth_root</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">digit_type</span> <span class="identifier">n</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Returns:</strong></span> The <code class="computeroutput"><span class="identifier">n</span></code>th
+        root of <code class="computeroutput"><span class="identifier">x</span></code>.
+      </li>
+<li>
+<span class="bold"><strong>Complexity:</strong></span> O(log(N)).
+      </li>
+<li>
+<span class="bold"><strong>Throws:</strong></span><div class="itemizedlist"><ul type="circle">
+<li><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code></li>
+<li>
+<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span></code> if <code class="computeroutput"><span class="identifier">x</span></code>
+            is negative and <code class="computeroutput"><span class="identifier">n</span></code> is
+            odd.
+          </li>
+</ul></div>
+</li>
+</ul></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="implementation_notes.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="mp_int_traits_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/mp_int_traits_reference.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/mp_int_traits_reference.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,78 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>mp_int_traits reference</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="mp_int_reference.html" title="mp_int reference">
+<link rel="next" href="uniform_mp_int_reference.html" title="uniform_mp_int reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="mp_int_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="uniform_mp_int_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.mp_int_traits_reference"></a><a class="link" href="mp_int_traits_reference.html" title="mp_int_traits reference">mp_int_traits reference</a>
+</h2></div></div></div>
+<p>
+      The second template parameter to mp_int is a type which allows to customize
+      some of mp_int's internal workings.
+    </p>
+<a name="mp_int_.mp_int_traits_reference.synopsis"></a><h4>
+<a name="id2787773"></a>
+      <a class="link" href="mp_int_traits_reference.html#mp_int_.mp_int_traits_reference.synopsis">Synopsis</a>
+    </h4>
+<p>
+      
+</p>
+<pre class="programlisting"><span class="comment">// <boost/mp_math/mp_int/traits.hpp>
+</span><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span>
+<span class="keyword">namespace</span> <span class="identifier">mp_math</span> <span class="special">{</span>
+
+<span class="keyword">template</span><span class="special"><</span>
+  <span class="keyword">typename</span> <span class="identifier">Digit</span> <span class="special">=</span> <span class="identifier">implementation</span> <span class="identifier">defined</span><span class="special">,</span>
+  <span class="keyword">typename</span> <span class="identifier">Word</span> <span class="special">=</span> <span class="identifier">implementation</span> <span class="identifier">defined</span>
+<span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">mp_int_traits</span>
+<span class="special">{</span>
+  <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="identifier">Digit</span>       <span class="identifier">digit_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="identifier">Word</span>        <span class="identifier">word_type</span><span class="special">;</span>
+
+  <span class="keyword">static</span> <span class="identifier">size_type</span> <span class="identifier">toom_mul_cutoff</span><span class="special">;</span>           <span class="comment">// default: 350
+</span>  <span class="keyword">static</span> <span class="identifier">size_type</span> <span class="identifier">toom_sqr_cutoff</span><span class="special">;</span>           <span class="comment">// default: 400
+</span>  <span class="keyword">static</span> <span class="identifier">size_type</span> <span class="identifier">karatsuba_mul_cutoff</span><span class="special">;</span>      <span class="comment">// default: 80
+</span>  <span class="keyword">static</span> <span class="identifier">size_type</span> <span class="identifier">karatsuba_sqr_cutoff</span><span class="special">;</span>      <span class="comment">// default: 120
+</span><span class="special">};</span>
+
+<span class="special">}</span> <span class="comment">// namespace mp_math
+</span><span class="special">}</span> <span class="comment">// namespace boost
+</span></pre>
+<p>
+    </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="mp_int_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="uniform_mp_int_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/performance.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/performance.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,228 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Performance</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="tutorial.html" title="Tutorial">
+<link rel="next" href="implementation_notes.html" title="Implementation notes">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tutorial.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.performance"></a><a class="link" href="performance.html" title="Performance">Performance</a>
+</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">Tips</span></dt>
+<dt><span class="section">Measurements</span></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.performance.tips"></a><a class="link" href="performance.html#mp_int_.performance.tips" title="Tips">Tips</a>
+</h3></div></div></div>
+<div class="itemizedlist"><ul type="disc">
+<li>
+          A statement like 
+<pre class="programlisting"><span class="identifier">x</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span><span class="special">;</span></pre>
+          involves the creation of a temporary <code class="computeroutput"><span class="identifier">mp_int</span></code>
+          inside <code class="computeroutput"><span class="keyword">operator</span> <span class="special">+</span></code>
+          because it is not able to write the result directly into <code class="computeroutput"><span class="identifier">x</span></code> which may already have enough memory
+          allocated to hold the result. Instead rewrite it into 
+<pre class="programlisting"><span class="identifier">x</span> <span class="special">=</span> <span class="identifier">a</span><span class="special">;</span>
+<span class="identifier">x</span> <span class="special">+=</span> <span class="identifier">b</span><span class="special">;</span>
+</pre>
+          This trick proves to be useful only for simple operations like addition
+          and subtraction.
+        </li>
+<li>
+          In operations involving built in integral types, try to use unsigned types,
+          preferrably unsigned types that are as large or smaller than mp_int<>::digit_type.
+        </li>
+<li>
+          Use hexadecimal digits for input and output. Conversion from/to power of
+          two bases uses a O(n) algorithm which is not possible for base 10.
+        </li>
+</ul></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.performance.measurements"></a><a class="link" href="performance.html#mp_int_.performance.measurements" title="Measurements">Measurements</a>
+</h3></div></div></div>
+<div class="toc"><dl><dt><span class="section"><a href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_">AMD
+        Athlon XP 2000+</a></span></dt></dl></div>
+<p>
+        A benchmark program is supplied with Boost.Mp_math under libs/mp_math/tools/benchmark.
+        This benchmark compares some primitive operations of different multi precision
+        integer libraries. It creates detailed result files and uses gnuplot
+        to create graphs.
+      </p>
+<p>
+        Example invocations:
+      </p>
+<pre class="programlisting">benchmark // runs all benches
+benchmark --help
+benchmark --ops="add subtract multiply" --libs="boost.mp_math libtommath"
+</pre>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_"></a><a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_" title="AMD Athlon XP 2000+">AMD
+        Athlon XP 2000+</a>
+</h4></div></div></div>
+<pre class="programlisting">Operating System: Arch Linux (i686), Kernel 2.6.26, glibc 2.8
+Compiler: gcc-4.3.2
+</pre>
+<p>
+          Libraries being compared:
+        </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+            Boost.Mp_math-1_36
+            <div class="itemizedlist"><ul type="circle"><li>
+                switches used: -ftemplate-depth-128 -O3 -finline-functions -march=i686
+                -mtune=generic -std=c++0x
+              </li></ul></div>
+</li>
+<li>
+            libtommath-0.41
+            <div class="itemizedlist"><ul type="circle"><li>
+                switches used: -ftemplate-depth-128 -O3 -finline-functions -march=i686
+                -mtune=generic
+              </li></ul></div>
+</li>
+<li>
+            gmp-4.2.2 (precompiled distribution package, uses generic i386 asm and
+            Intel P6 (Pentium Pro) asm where available)
+            <div class="itemizedlist"><ul type="circle"><li>
+                switches used: -march=i686 -mtune=generic -O2
+              </li></ul></div>
+</li>
+</ul></div>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.input_vectors"></a><h4>
+<a name="id2744932"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.input_vectors">Input
+          vectors</a>
+        </h4>
+<p>
+          Operand size is measured in number of bits. I chose to vary the operand
+          size for the benchmarks a little to see how well the operation handles
+          inputs of differing sizes. Benchmarks that use only one operand use operand
+          1. <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/input_vecs.png" alt="input_vecs"></span>
+        </p>
+<p>
+          While input operand 1 grows linearly, input operand 2's size is determined
+          by a modified sine function.
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.construct_from_decimal_string"></a><h4>
+<a name="id2744980"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.construct_from_decimal_string">Construct
+          from decimal string</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/ctor_dec.png" alt="ctor_dec"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.construct_from_hex_string"></a><h4>
+<a name="id2745020"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.construct_from_hex_string">Construct
+          from hex string</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/ctor_hex.png" alt="ctor_hex"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.conversion_to_decimal_string"></a><h4>
+<a name="id2745059"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.conversion_to_decimal_string">Conversion
+          to decimal string</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/to_dec.png" alt="to_dec"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.conversion_to_hex_string"></a><h4>
+<a name="id2745099"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.conversion_to_hex_string">Conversion
+          to hex string</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/to_hex.png" alt="to_hex"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.add"></a><h4>
+<a name="id2745137"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.add">Add</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/add.png" alt="add"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.subtract"></a><h4>
+<a name="id2745173"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.subtract">Subtract</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/subtract.png" alt="subtract"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.multiply"></a><h4>
+<a name="id2745210"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.multiply">Multiply</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/multiply.png" alt="multiply"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.divide"></a><h4>
+<a name="id2745246"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.divide">Divide</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/divide.png" alt="divide"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.modulo"></a><h4>
+<a name="id2745283"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.modulo">Modulo</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/modulo.png" alt="modulo"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.square"></a><h4>
+<a name="id2745319"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.square">Square</a>
+        </h4>
+<p>
+          <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/square.png" alt="square"></span>
+        </p>
+<a name="mp_int_.performance.measurements.amd_athlon_xp_2000_.modular_power"></a><h4>
+<a name="id2745356"></a>
+          <a class="link" href="performance.html#mp_int_.performance.measurements.amd_athlon_xp_2000_.modular_power">Modular
+          Power</a>
+        </h4>
+<p>
+          The operation looks like this: <code class="computeroutput"><span class="identifier">dest</span>
+          <span class="special">=</span> <span class="special">(</span><span class="identifier">op1</span> <span class="special">^</span> <span class="identifier">op1</span><span class="special">)</span> <span class="special">%</span> <span class="identifier">op2</span></code>.
+          This graph uses a logarithmic scale. <span class="inlinemediaobject"><img src="../benchmark_imgs/k7/modpow.png" alt="modpow"></span>
+        </p>
+</div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tutorial.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/primality_tests_reference.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/primality_tests_reference.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,209 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Primality Tests reference</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="uniform_mp_int_bits_reference.html" title="uniform_mp_int_bits reference">
+<link rel="next" href="bibliography.html" title="Bibliography">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="uniform_mp_int_bits_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="bibliography.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.primality_tests_reference"></a><a class="link" href="primality_tests_reference.html" title="Primality Tests reference">Primality Tests reference</a>
+</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">primality_division_test</span></dt>
+<dt><span class="section">primality_fermat_test</span></dt>
+<dt><span class="section">primality_miller_rabin_test</span></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.primality_tests_reference.primality_division_test"></a><a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_division_test" title="primality_division_test">primality_division_test</a>
+</h3></div></div></div>
+<p>
+        This function object tests a candidate <code class="computeroutput"><span class="identifier">p</span></code>
+        by repeatedly dividing it by small primes (2, 3, 5, 7, 11...). This is a
+        test that should be used before other more complex tests because it quickly
+        sieves out composite numbers. For example, testing for 2, 5, 7 will eliminate
+        54% of all numbers, testing for all primes less than 100 eliminates 70%,
+        for all primes less than 256 it is 80%.
+      </p>
+<a name="mp_int_.primality_tests_reference.primality_division_test.synopsis"></a><h5>
+<a name="id2789739"></a>
+        <a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_division_test.synopsis">Synopsis</a>
+      </h5>
+<pre class="programlisting"><span class="comment">// <boost/mp_math/mp_int.hpp>
+</span><span class="keyword">struct</span> <span class="identifier">primality_division_test</span>
+<span class="special">{</span>
+  <span class="keyword">typedef</span> <span class="keyword">bool</span> <span class="identifier">result_type</span><span class="special">;</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+  <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<a name="mp_int_.primality_tests_reference.primality_division_test.members"></a><h4>
+<a name="id2789926"></a>
+        <a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_division_test.members">Members</a>
+      </h4>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Returns true if <code class="computeroutput"><span class="identifier">p</span></code> is probably prime. Returns false if
+          <code class="computeroutput"><span class="identifier">p</span></code> is definitely composite.
+        </li></ul></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.primality_tests_reference.primality_fermat_test"></a><a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_fermat_test" title="primality_fermat_test">primality_fermat_test</a>
+</h3></div></div></div>
+<p>
+        This test is based on Fermat's little theorem which states that if an integer
+        <code class="computeroutput"><span class="identifier">p</span></code> is prime, then for all
+        integers <code class="computeroutput"><span class="identifier">a</span></code> where 0 <
+        <code class="computeroutput"><span class="identifier">a</span></code> < <code class="computeroutput"><span class="identifier">p</span></code>
+      </p>
+<p>
+        <code class="computeroutput"><span class="identifier">a</span><span class="special">**(</span><span class="identifier">p</span><span class="special">-</span><span class="number">1</span><span class="special">)</span> <span class="special">=</span> <span class="number">1</span>
+        <span class="special">(</span><span class="identifier">mod</span>
+        <span class="identifier">p</span><span class="special">)</span></code>
+      </p>
+<p>
+        an alternative formulation is
+      </p>
+<p>
+        <code class="computeroutput"><span class="identifier">a</span><span class="special">**</span><span class="identifier">p</span> <span class="special">=</span> <span class="identifier">a</span>
+        <span class="special">(</span><span class="identifier">mod</span>
+        <span class="identifier">p</span><span class="special">)</span></code>
+      </p>
+<p>
+        For each round the test creates a random base <code class="computeroutput"><span class="identifier">a</span></code>
+        and checks if the condition holds. There is a class of pseudoprimes called
+        carmichael numbers which are less likely though not impossible with enough
+        rounds to be detected by this test.
+      </p>
+<a name="mp_int_.primality_tests_reference.primality_fermat_test.synopsis"></a><h5>
+<a name="id2790306"></a>
+        <a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_fermat_test.synopsis">Synopsis</a>
+      </h5>
+<pre class="programlisting"><span class="comment">// <boost/mp_math/mp_int.hpp>
+</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Distribution</span> <span class="special">=</span> <span class="identifier">uniform_mp_int</span><span class="special"><></span> <span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">primality_fermat_test</span>
+<span class="special">{</span>
+  <span class="keyword">typedef</span> <span class="identifier">Distribution</span> <span class="identifier">distribution_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="keyword">bool</span>         <span class="identifier">result_type</span><span class="special">;</span>
+
+  <span class="keyword">explicit</span> <span class="identifier">primality_fermat_test</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">rounds</span><span class="special">);</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Engine</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+  <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Engine</span><span class="special">&</span> <span class="identifier">e</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<a name="mp_int_.primality_tests_reference.primality_fermat_test.members"></a><h4>
+<a name="id2790631"></a>
+        <a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_fermat_test.members">Members</a>
+      </h4>
+<pre class="programlisting"><span class="keyword">explicit</span> <span class="identifier">primality_fermat_test</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">r</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Constructs a <code class="computeroutput"><span class="identifier">primality_fermat_test</span></code>
+          object with the number of test rounds given by <code class="computeroutput"><span class="identifier">r</span></code>.
+        </li></ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Engine</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Engine</span><span class="special">&</span> <span class="identifier">e</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Returns true if <code class="computeroutput"><span class="identifier">p</span></code> is probably prime. Returns false if
+          <code class="computeroutput"><span class="identifier">p</span></code> is definitely composite.
+        </li></ul></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.primality_tests_reference.primality_miller_rabin_test"></a><a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_miller_rabin_test" title="primality_miller_rabin_test">primality_miller_rabin_test</a>
+</h3></div></div></div>
+<p>
+        This test is an improved version of the Fermat primality test that will also
+        detect carmichael numbers.
+      </p>
+<a name="mp_int_.primality_tests_reference.primality_miller_rabin_test.synopsis"></a><h5>
+<a name="id2790943"></a>
+        <a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_miller_rabin_test.synopsis">Synopsis</a>
+      </h5>
+<pre class="programlisting"><span class="comment">// <boost/mp_math/mp_int.hpp>
+</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Distribution</span> <span class="special">=</span> <span class="identifier">uniform_mp_int</span><span class="special"><></span> <span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">primality_miller_rabin_test</span>
+<span class="special">{</span>
+  <span class="keyword">typedef</span> <span class="identifier">Distribution</span> <span class="identifier">distribution_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="keyword">bool</span>         <span class="identifier">result_type</span><span class="special">;</span>
+
+  <span class="keyword">explicit</span> <span class="identifier">primality_miller_rabin_test</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">r</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span>
+
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Engine</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+  <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Engine</span><span class="special">&</span> <span class="identifier">e</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="keyword">static</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">recommended_number_of_rounds</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">bits</span><span class="special">);</span>
+<span class="special">};</span>
+</pre>
+<a name="mp_int_.primality_tests_reference.primality_miller_rabin_test.members"></a><h4>
+<a name="id2791319"></a>
+        <a class="link" href="primality_tests_reference.html#mp_int_.primality_tests_reference.primality_miller_rabin_test.members">Members</a>
+      </h4>
+<pre class="programlisting"><span class="keyword">explicit</span> <span class="identifier">primality_miller_rabin_test</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">r</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Constructs a <code class="computeroutput"><span class="identifier">primality_miller_rabin_test</span></code>
+          object with the number of test rounds given by <code class="computeroutput"><span class="identifier">r</span></code>.
+          If <code class="computeroutput"><span class="identifier">r</span> <span class="special">==</span>
+          <span class="number">0</span></code> then each invocation of this function
+          object will use the recommended number of rounds.
+        </li></ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Engine</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">A</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Engine</span><span class="special">&</span> <span class="identifier">e</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><</span><span class="identifier">A</span><span class="special">,</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">p</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires:</strong></span><code class="computeroutput"><span class="identifier">p</span></code>
+          is odd.
+        </li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Returns true if <code class="computeroutput"><span class="identifier">p</span></code> is probably prime. Returns false if
+          <code class="computeroutput"><span class="identifier">p</span></code> is definitely composite.
+        </li>
+</ul></div>
+<pre class="programlisting"><span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">recommended_number_of_rounds</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">bits</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Returns the recommended number
+          of rounds for a number of precision <code class="computeroutput"><span class="identifier">bits</span></code>
+          so that the probability of error is less than 2^-96.
+        </li></ul></div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="uniform_mp_int_bits_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="bibliography.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/tutorial.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/tutorial.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,262 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Tutorial</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="../index.html" title="Chapter 1. mp_int">
+<link rel="next" href="performance.html" title="Performance">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="performance.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.tutorial"></a><a class="link" href="tutorial.html" title="Tutorial">Tutorial</a>
+</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">General use</span></dt>
+<dt><span class="section"><a href="tutorial.html#mp_int_.tutorial.random_number_generation">Random number
+      generation</a></span></dt>
+<dt><span class="section">Primality testing</span></dt>
+<dt><span class="section"><a href="tutorial.html#mp_int_.tutorial.prime_number_generation">Prime number
+      generation</a></span></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.tutorial.general_use"></a><a class="link" href="tutorial.html#mp_int_.tutorial.general_use" title="General use">General use</a>
+</h3></div></div></div>
+<p>
+        The only header you need to include to use the library is <code class="computeroutput"><span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">mp_math</span><span class="special">/</span><span class="identifier">mp_int</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code>.
+        This is a header-only library so deployment is easy. All functions and objects
+        of this library live in namespace <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mp_math</span></code>.
+      </p>
+<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">string</span><span class="special">></span>
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">mp_math</span><span class="special">/</span><span class="identifier">mp_int</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+
+<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mp_math</span><span class="special">;</span>
+<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span>
+
+<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
+<span class="special">{</span>
+  <span class="comment">// init from string
+</span>  <span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">x</span><span class="special">(</span><span class="string">"93423894782394782347823947289374"</span><span class="special">);</span>
+  <span class="comment">// init from integral type
+</span>  <span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">y</span> <span class="special">=</span> <span class="number">2340</span><span class="special">;</span>
+  <span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">z</span> <span class="special">=</span> <span class="identifier">x</span> <span class="special">*</span> <span class="identifier">y</span><span class="special">;</span>
+
+  <span class="comment">// stream output reacts to stream flags
+</span>  <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">hex</span> <span class="special"><<</span> <span class="identifier">z</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>
+
+  <span class="comment">// automatic detection of radix using the base prefix 0x
+</span>  <span class="identifier">z</span> <span class="special">=</span> <span class="string">"0xaaaabbbbccccddddeeeeffff222255557777"</span><span class="special">;</span>
+  
+  <span class="identifier">z</span> <span class="special">/=</span> <span class="identifier">y</span><span class="special">;</span>
+
+  <span class="comment">// explicit conversion to string according to formatting flags
+</span>  <span class="identifier">string</span> <span class="identifier">s</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">.</span><span class="identifier">to_string</span><span class="special"><</span><span class="identifier">string</span><span class="special">>(</span><span class="identifier">ios</span><span class="special">::</span><span class="identifier">hex</span> <span class="special">|</span> <span class="identifier">ios</span><span class="special">::</span><span class="identifier">showbase</span><span class="special">);</span>
+  <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">s</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>
+
+  <span class="identifier">z</span> <span class="special">-=</span> <span class="identifier">z</span><span class="special">;</span>
+
+  <span class="comment">// explicit conversion to built in integral types - this will throw
+</span>  <span class="comment">// std::overflow_error if int does not have enough precision to hold the
+</span>  <span class="comment">// result
+</span>  <span class="keyword">int</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">.</span><span class="identifier">to_integral</span><span class="special"><</span><span class="keyword">int</span><span class="special">>();</span>
+  
+  <span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
+<span class="special">}</span>
+</pre>
+<p>
+        In most cases the <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        type will behave like a built in integral type.
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.tutorial.random_number_generation"></a><a class="link" href="tutorial.html#mp_int_.tutorial.random_number_generation" title="Random number generation">Random number
+      generation</a>
+</h3></div></div></div>
+<p>
+        The random number generators have interfaces similar to Boost.Random. Including
+        <code class="computeroutput"><span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">random</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code>
+        is not necessary because it is used internally by the <code class="computeroutput"><span class="identifier">mp_int</span></code>
+        random machinery. The random number engine <code class="computeroutput"><span class="identifier">mt19937</span></code>
+        that we use from here on lives in namespace <code class="computeroutput"><span class="identifier">boost</span></code>.
+      </p>
+<pre class="programlisting"><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">min</span><span class="special">(</span><span class="number">0U</span><span class="special">);</span>
+<span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">max</span><span class="special">(</span><span class="string">"0x8974651231456456564"</span><span class="special">);</span>
+
+<span class="identifier">uniform_mp_int</span><span class="special"><></span> <span class="identifier">generator</span><span class="special">(</span><span class="identifier">min</span><span class="special">,</span> <span class="identifier">max</span><span class="special">);</span>
+
+<span class="comment">// Choose a random number engine.
+</span><span class="identifier">mt19937</span> <span class="identifier">e</span><span class="special">;</span>
+
+<span class="comment">// Now generate a random number.
+</span><span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">generator</span><span class="special">(</span><span class="identifier">e</span><span class="special">);</span>
+</pre>
+<p>
+        Another probably more useful alternative is to generate random numbers of
+        a certain precision measured in bits.
+      </p>
+<pre class="programlisting"><span class="comment">// A generator for 2048 bit integers.
+</span><span class="identifier">uniform_mp_int_bits</span><span class="special"><></span> <span class="identifier">generator</span><span class="special">(</span><span class="number">2048</span><span class="special">);</span>
+
+<span class="identifier">mt19937</span> <span class="identifier">e</span><span class="special">;</span>
+<span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">generator</span><span class="special">(</span><span class="identifier">e</span><span class="special">);</span>
+</pre>
+<p>
+        Note that the numbers will always be 2048 bits large, i.e. the most significant
+        bit is always set to 1.
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.tutorial.primality_testing"></a><a class="link" href="tutorial.html#mp_int_.tutorial.primality_testing" title="Primality testing">Primality testing</a>
+</h3></div></div></div>
+<p>
+        Currently all primality tests in this library are probabilistic. A probabilistic
+        primality test cannot ascertain that a prime candidate p is really prime.
+        It can however ascertain that it is a composite number.
+      </p>
+<p>
+        Here we will learn how to test a number <code class="computeroutput"><span class="identifier">p</span></code>
+        for primality using the fermat primality test. We use boost::bind to bind
+        the random number engine to the test functor. That is necessary because the
+        test functor's function invocation operator needs the random number engine.
+        The operator looks like this:
+      </p>
+<pre class="programlisting"><span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Engine</span><span class="special">&</span> <span class="identifier">e</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><>&</span> <span class="identifier">p</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<p>
+        We need to bind the random number engine to the first parameter slot. Let's
+        do it!
+      </p>
+<pre class="programlisting"><span class="comment">// Create the fermat test functor with 4 rounds of testing.
+</span><span class="identifier">primality_fermat_test</span><span class="special"><></span> <span class="identifier">test</span><span class="special">(</span><span class="number">4</span><span class="special">);</span>
+
+<span class="comment">// Create a random number engine.
+</span><span class="identifier">mt19937</span> <span class="identifier">rng</span><span class="special">;</span>
+
+<span class="comment">// Create a random 1024 bit candidate number.
+</span><span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">p</span> <span class="special">=</span> <span class="identifier">uniform_mp_int_bits</span><span class="special"><>(</span><span class="number">1024</span><span class="special">)(</span><span class="identifier">rng</span><span class="special">);</span>
+
+<span class="keyword">bool</span> <span class="identifier">is_p_prime</span> <span class="special">=</span> <span class="identifier">is_prime</span><span class="special">(</span><span class="identifier">p</span><span class="special">,</span> <span class="identifier">bind</span><span class="special">(</span><span class="identifier">test</span><span class="special">,</span> <span class="identifier">rng</span><span class="special">,</span> <span class="identifier">_1</span><span class="special">));</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="mp_int_.tutorial.prime_number_generation"></a><a class="link" href="tutorial.html#mp_int_.tutorial.prime_number_generation" title="Prime number generation">Prime number
+      generation</a>
+</h3></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">prime_generator</span></dt>
+<dt><span class="section">safe_prime_generator</span></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="mp_int_.tutorial.prime_number_generation.prime_generator"></a><a class="link" href="tutorial.html#mp_int_.tutorial.prime_number_generation.prime_generator" title="prime_generator">prime_generator</a>
+</h4></div></div></div>
+<p>
+          First we will look at how to generate prime numbers using a simple trial
+          division test. What this means is that the prime generator creates a random
+          number and then repeatedly divides it by small primes until it finds a
+          number that passes this test.
+        </p>
+<pre class="programlisting"><span class="comment">// Create a generator for 2048 bit primes.
+</span><span class="identifier">prime_generator</span><span class="special"><</span><span class="identifier">primality_division_test</span><span class="special">></span> <span class="identifier">generator</span><span class="special">(</span><span class="number">2048</span><span class="special">);</span>
+
+<span class="comment">// Create a random number engine.
+</span><span class="identifier">mt19937</span> <span class="identifier">rng</span><span class="special">;</span>
+
+<span class="comment">// Now create a prime.
+</span><span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">prime</span> <span class="special">=</span> <span class="identifier">generator</span><span class="special">(</span><span class="identifier">rng</span><span class="special">);</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="mp_int_.tutorial.prime_number_generation.safe_prime_generator"></a><a class="link" href="tutorial.html#mp_int_.tutorial.prime_number_generation.safe_prime_generator" title="safe_prime_generator">safe_prime_generator</a>
+</h4></div></div></div>
+<p>
+          A safe prime is a prime <code class="computeroutput"><span class="identifier">p</span></code>
+          for which <code class="computeroutput"><span class="special">(</span><span class="identifier">p</span><span class="special">-</span><span class="number">1</span><span class="special">)/</span><span class="number">2</span></code> is also prime. Such prime numbers are much
+          rarer and thus take longer to generate.
+        </p>
+<p>
+          Now we will look at how to use a more sophisticated primality test like
+          <code class="computeroutput"><span class="identifier">primality_miller_rabin_test</span></code>
+          for prime number generation. It is very useful to combine this test with
+          the <code class="computeroutput"><span class="identifier">primality_division_test</span></code>.
+          This will involve a bit of code, mostly because <code class="computeroutput"><span class="identifier">primality_miller_rabin_test</span></code>
+          and <code class="computeroutput"><span class="identifier">safe_prime_generator</span></code>
+          require a random number generator. The latter needs randomness to create
+          a candidate to test for primality and the miller rabin test needs randomness
+          to test the candidate effectively.
+        </p>
+<pre class="programlisting"><span class="comment">// Define a function object that checks a prime candidate p first with a trial
+</span><span class="comment">// division and then with the miller-rabin algorithm. For ease of use we give
+</span><span class="comment">// it default template arguments.
+</span><span class="comment">// It does not hold a reference to the random number engine because that could
+</span><span class="comment">// lead to lifetime problems.
+</span><span class="keyword">template</span><span class="special"><</span>
+  <span class="keyword">class</span> <span class="identifier">Engine</span> <span class="special">=</span> <span class="identifier">mt19937</span><span class="special">,</span>
+  <span class="keyword">class</span> <span class="identifier">Distribution</span> <span class="special">=</span> <span class="identifier">uniform_mp_int_bits</span><span class="special"><></span>
+<span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">primality_test</span>
+<span class="special">{</span>
+  <span class="identifier">primality_division_test</span>                   <span class="identifier">test1</span><span class="special">;</span>
+  <span class="identifier">primality_miller_rabin_test</span><span class="special"><</span><span class="identifier">Distribution</span><span class="special">></span> <span class="identifier">test2</span><span class="special">;</span>
+  <span class="identifier">Engine</span> <span class="identifier">rng</span><span class="special">;</span>
+
+  <span class="keyword">explicit</span> <span class="identifier">tester</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">Engine</span><span class="special">&</span> <span class="identifier">e</span> <span class="special">=</span> <span class="identifier">Engine</span><span class="special">())</span> <span class="special">:</span> <span class="identifier">rng</span><span class="special">(</span><span class="identifier">e</span><span class="special">)</span> <span class="special">{}</span>
+
+  <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">const</span> <span class="identifier">mp_int</span><span class="special"><>&</span> <span class="identifier">p</span><span class="special">)</span>
+  <span class="special">{</span>
+    <span class="keyword">return</span> <span class="identifier">test1</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span> <span class="special">&&</span> <span class="identifier">test2</span><span class="special">(</span><span class="identifier">rng</span><span class="special">,</span> <span class="identifier">p</span><span class="special">);</span>
+  <span class="special">}</span>
+<span class="special">};</span>
+
+<span class="comment">// Create a random number engine that we will feed to the different
+</span><span class="comment">// algorithms.
+</span><span class="identifier">mt19937</span> <span class="identifier">rng</span><span class="special">;</span>
+
+<span class="comment">// Create a generator for safe primes with 128 bits precision.
+</span><span class="keyword">typedef</span> <span class="identifier">safe_prime_generator</span><span class="special"><</span><span class="identifier">primality_test</span><span class="special"><>,</span> <span class="identifier">uniform_mp_int_bits</span><span class="special"><></span> <span class="special">></span>
+  <span class="identifier">generator_type</span><span class="special">;</span>
+
+<span class="identifier">generator_type</span> <span class="identifier">generator</span><span class="special">(</span><span class="number">128</span><span class="special">,</span> <span class="identifier">primality_test</span><span class="special"><>(</span><span class="identifier">rng</span><span class="special">));</span>
+
+<span class="identifier">mp_int</span><span class="special"><></span> <span class="identifier">prime</span> <span class="special">=</span> <span class="identifier">generator</span><span class="special">(</span><span class="identifier">rng</span><span class="special">);</span>
+</pre>
+<p>
+          Remember, the generated numbers are <span class="emphasis"><em>probably</em></span> prime.
+        </p>
+</div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="performance.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/uniform_mp_int_bits_reference.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/uniform_mp_int_bits_reference.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,102 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>uniform_mp_int_bits reference</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="uniform_mp_int_reference.html" title="uniform_mp_int reference">
+<link rel="next" href="primality_tests_reference.html" title="Primality Tests reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="uniform_mp_int_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="primality_tests_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.uniform_mp_int_bits_reference"></a><a class="link" href="uniform_mp_int_bits_reference.html" title="uniform_mp_int_bits reference">uniform_mp_int_bits
+    reference</a>
+</h2></div></div></div>
+<a name="mp_int_.uniform_mp_int_bits_reference.synopsis"></a><h4>
+<a name="id2788984"></a>
+      <a class="link" href="uniform_mp_int_bits_reference.html#mp_int_.uniform_mp_int_bits_reference.synopsis">Synopsis</a>
+    </h4>
+<pre class="programlisting"><span class="comment">// <boost/mp_math/mp_int.hpp>
+</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">MpInt</span> <span class="special">=</span> <span class="identifier">mp_int</span><span class="special"><></span> <span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">uniform_mp_int_bits</span>
+<span class="special">{</span>
+  <span class="keyword">typedef</span> <span class="identifier">MpInt</span> <span class="identifier">input_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="identifier">MpInt</span> <span class="identifier">result_type</span><span class="special">;</span>
+
+  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">has_fixed_range</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
+
+  <span class="identifier">uniform_mp_int_bits</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">MpInt</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">bits</span><span class="special">);</span>
+
+  <span class="identifier">result_type</span> <span class="identifier">min</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+  <span class="identifier">result_type</span> <span class="identifier">max</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="keyword">void</span> <span class="identifier">reset</span><span class="special">();</span>
+  
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">UniformRandomNumberGenerator</span><span class="special">></span>
+  <span class="identifier">result_type</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">UniformRandomNumberGenerator</span><span class="special">&</span> <span class="identifier">urng</span><span class="special">);</span>
+<span class="special">};</span>
+</pre>
+<a name="mp_int_.uniform_mp_int_bits_reference.members"></a><h4>
+<a name="id2789332"></a>
+      <a class="link" href="uniform_mp_int_bits_reference.html#mp_int_.uniform_mp_int_bits_reference.members">Members</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">uniform_mp_int_bits</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">MpInt</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">x</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Constructs a <code class="computeroutput"><span class="identifier">uniform_mp_int_bits</span></code>
+        object. All numbers generated by this object will be <code class="computeroutput"><span class="identifier">x</span></code>
+        bits in size.
+      </li></ul></div>
+<pre class="programlisting"><span class="identifier">result_type</span> <span class="identifier">min</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Returns:</strong></span> The least value of the distribution.
+      </li></ul></div>
+<pre class="programlisting"><span class="identifier">result_type</span> <span class="identifier">max</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Returns:</strong></span> The greatest value of the distribution.
+      </li></ul></div>
+<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">reset</span><span class="special">();</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Resets the state of the distribution
+        function.
+      </li></ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">UniformRandomNumberGenerator</span><span class="special">></span>
+<span class="identifier">result_type</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">UniformRandomNumberGenerator</span><span class="special">&</span> <span class="identifier">urng</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Returns:</strong></span> A uniform random number <code class="computeroutput"><span class="identifier">x</span></code> in the range <code class="computeroutput"><span class="identifier">min</span>
+        <span class="special"><=</span> <span class="identifier">x</span>
+        <span class="special"><=</span> <span class="identifier">max</span></code>.
+      </li></ul></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="uniform_mp_int_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="primality_tests_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/html/mp_int_/uniform_mp_int_reference.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/html/mp_int_/uniform_mp_int_reference.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,108 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>uniform_mp_int reference</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
+<link rel="start" href="../index.html" title="Chapter 1. mp_int">
+<link rel="up" href="../index.html" title="Chapter 1. mp_int">
+<link rel="prev" href="mp_int_traits_reference.html" title="mp_int_traits reference">
+<link rel="next" href="uniform_mp_int_bits_reference.html" title="uniform_mp_int_bits reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="mp_int_traits_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="uniform_mp_int_bits_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="mp_int_.uniform_mp_int_reference"></a><a class="link" href="uniform_mp_int_reference.html" title="uniform_mp_int reference">uniform_mp_int reference</a>
+</h2></div></div></div>
+<a name="mp_int_.uniform_mp_int_reference.synopsis"></a><h4>
+<a name="id2788164"></a>
+      <a class="link" href="uniform_mp_int_reference.html#mp_int_.uniform_mp_int_reference.synopsis">Synopsis</a>
+    </h4>
+<pre class="programlisting"><span class="comment">// <boost/mp_math/mp_int.hpp>
+</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">MpInt</span> <span class="special">=</span> <span class="identifier">mp_int</span><span class="special"><></span> <span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">uniform_mp_int</span>
+<span class="special">{</span>
+  <span class="keyword">typedef</span> <span class="identifier">MpInt</span> <span class="identifier">input_type</span><span class="special">;</span>
+  <span class="keyword">typedef</span> <span class="identifier">MpInt</span> <span class="identifier">result_type</span><span class="special">;</span>
+
+  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">has_fixed_range</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
+
+  <span class="identifier">uniform_mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">MpInt</span><span class="special">&</span> <span class="identifier">min</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">MpInt</span><span class="special">&</span> <span class="identifier">max</span><span class="special">);</span>
+
+  <span class="identifier">result_type</span> <span class="identifier">min</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+  <span class="identifier">result_type</span> <span class="identifier">max</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+
+  <span class="keyword">void</span> <span class="identifier">reset</span><span class="special">();</span>
+  
+  <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">UniformRandomNumberGenerator</span><span class="special">></span>
+  <span class="identifier">result_type</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">UniformRandomNumberGenerator</span><span class="special">&</span> <span class="identifier">urng</span><span class="special">);</span>
+<span class="special">};</span>
+</pre>
+<a name="mp_int_.uniform_mp_int_reference.members"></a><h4>
+<a name="id2788532"></a>
+      <a class="link" href="uniform_mp_int_reference.html#mp_int_.uniform_mp_int_reference.members">Members</a>
+    </h4>
+<pre class="programlisting"><span class="identifier">uniform_mp_int</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">MpInt</span><span class="special">&</span> <span class="identifier">min</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">MpInt</span><span class="special">&</span> <span class="identifier">max</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<span class="bold"><strong>Requires: </strong></span><code class="computeroutput"><span class="identifier">min</span>
+        <span class="special"><=</span> <span class="identifier">max</span></code>
+</li>
+<li>
+<span class="bold"><strong>Effects:</strong></span> Constructs a <code class="computeroutput"><span class="identifier">uniform_mp_int</span></code>
+        object. <code class="computeroutput"><span class="identifier">min</span></code> and <code class="computeroutput"><span class="identifier">max</span></code> are the parameters of the distribution.
+      </li>
+</ul></div>
+<pre class="programlisting"><span class="identifier">result_type</span> <span class="identifier">min</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Returns:</strong></span> The <code class="computeroutput"><span class="identifier">min</span></code>
+        parameter of the distribution.
+      </li></ul></div>
+<pre class="programlisting"><span class="identifier">result_type</span> <span class="identifier">max</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Returns:</strong></span> The <code class="computeroutput"><span class="identifier">max</span></code>
+        parameter of the distribution.
+      </li></ul></div>
+<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">reset</span><span class="special">();</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Effects:</strong></span> Resets the state of the distribution
+        function.
+      </li></ul></div>
+<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">UniformRandomNumberGenerator</span><span class="special">></span>
+<span class="identifier">result_type</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">UniformRandomNumberGenerator</span><span class="special">&</span> <span class="identifier">urng</span><span class="special">);</span>
+</pre>
+<div class="itemizedlist"><ul type="disc"><li>
+<span class="bold"><strong>Returns:</strong></span> A uniform random number <code class="computeroutput"><span class="identifier">x</span></code> in the range <code class="computeroutput"><span class="identifier">min</span>
+        <span class="special"><=</span> <span class="identifier">x</span>
+        <span class="special"><=</span> <span class="identifier">max</span></code>.
+      </li></ul></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><div class="copyright-footer">Copyright © 2008 Kevin Sopp<p>
+        All code and documentation is in the public domain
+      </p>
+</div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="mp_int_traits_reference.html"><img src="../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="uniform_mp_int_bits_reference.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: sandbox/mp_math/libs/mp_math/doc/implementation_notes.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/implementation_notes.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,48 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section Implementation notes]
+
+[section mp_int structure]
+
+An `mp_int` is handled in a sign plus magnitude representation which looks like
+this:
+
+  struct mp_int
+  {
+    digit_type* digits_;
+    size_type used_, capacity_;
+    int sign_;
+  };
+
+The least significant digit of the number always lives at `digits_[0]` while the
+most significant lives at `digits_[used_ - 1]`.
+
+Libtommath on which this code is ultimately based chose a `digit_type`
+representation which does not use all of its bits, instead some bits are
+reserved to hold carries in intermediate results. This allows very fast
+multiplication routines. I chose a different representation which uses all the
+bits in the `digit_type` but needs explicit carry handling in the code. This
+makes normal c++ code a tad slower. However it makes it much easier to write
+assembler routines since most CPUs provide instructions that allow the handling
+of carries in place. This is what GMP does as well. It is possible that a
+`digit_type` representation similar to libtommath's returns someday which can
+then be enabled via a different `mp_int_traits` class template.
+
+[endsect][/How mp_int structure]
+
+
+[section Semantics]
+
+* An integer with a value of zero has a `used_` count of 1 and `digits_[0]`
+holds the value 0.
+* An unitialized integer has no value and all operations on it except for
+initializing or swapping are undefined.
+
+[endsect][/Semantics]
+
+
+[endsect][/Implementation notes]
+
Added: sandbox/mp_math/libs/mp_math/doc/introduction.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/introduction.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,23 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section Introduction]
+This library provides the `mp_int` class template for arbitrary precision signed
+integers. These integers grow dynamically as needed. Additionally, special
+functions which are necessary for the implementation of public key cryptography
+such as prime generation are provided.
+
+[heading Acknowledgement]
+
+This library originally started as a port of the C code of libtommath. Without
+the huge amount of work done by its author Tom St. Denis, this library wouldn't
+have been possible. Not only does he provide free C code, but also a very
+detailed pdf document of over 200 pages explaining the algorithms used in his
+code. Both his documentation and his code were placed in the public domain. In
+the spirit of his work the code of the `mp_int` library and its documentation
+are placed in the [*public domain] as well.
+
+[endsect]
+
Added: sandbox/mp_math/libs/mp_math/doc/jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/jamfile.v2	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,28 @@
+# Copyright Kevin Sopp 2008.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+
+import quickbook ;
+
+xml mp_int : mp_int.qbk ;
+
+#boostbook standalone
+#  :
+#    mp_int mp_int
+#  ;
+
+boostbook standalone
+  :
+    mp_int
+  :
+    <xsl:param>boost.root=../../../..
+    <xsl:param>boost.libraries=../../../../libs/libraries.htm
+    #<xsl:param>generate.section.toc.level=4
+    #<xsl:param>toc.max.depth=3
+    #<xsl:param>toc.section.depth=4
+    #<xsl:param>chunk.section.depth=1
+    #<xsl:param>chunk.first.sections=1
+  ;
+
Added: sandbox/mp_math/libs/mp_math/doc/mp_int.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/mp_int.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,29 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[library mp_int 
+  [quickbook 1.4]
+  [id mp_int]
+  [dirname mp_int]
+  [copyright 2008 Kevin Sopp]
+  [purpose multi precision integer arithmetic]
+  [authors [Sopp, Kevin]]
+  [license Distributed under the Boost Software License, Version 1.0.
+           (See accompanying file LICENSE_1_0.txt or copy at
+           [@http://www.boost.org/LICENSE_1_0.txt]
+  [source-mode c++]
+]
+
+[include introduction.qbk]
+[include tutorial.qbk]
+[include performance.qbk]
+[include implementation_notes.qbk]
+[include mp_int_reference.qbk]
+[include mp_int_traits_reference.qbk]
+[include uniform_mp_int_reference.qbk]
+[include uniform_mp_int_bits_reference.qbk]
+[include primality_tests_reference.qbk]
+[include bibliography.qbk]
+
Added: sandbox/mp_math/libs/mp_math/doc/mp_int_reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/mp_int_reference.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,1439 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section mp_int reference]
+
+[heading Synopsis]
+
+  // <boost/mp_math/mp_int.hpp>
+  namespace boost {
+  namespace mp_math {
+
+  template<
+    class Allocator = std::allocator<void>,
+    class Traits = mp_int_traits<>
+  >
+  struct mp_int
+  {
+    typedef Allocator allocator_type;
+    typedef Traits    traits_type;
+    typedef typename traits_type::size_type size_type;
+
+    // ctor/cctor/dtor/assign
+    mp_int();
+
+    template<typename IntegralT>
+    mp_int(IntegralT x, typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
+    
+    mp_int(const char* s);
+    mp_int(const wchar_t* s);
+
+    template<typename charT, class traits, class Alloc>
+    mp_int(const std::basic_string<charT,traits,Alloc>& s);
+    
+    template<typename RandomAccessIterator>
+    mp_int(RandomAccessIterator first, RandomAccessIterator last);
+    
+    mp_int(const char* s, std::ios_base::fmtflags f);
+    mp_int(const wchar_t* s, std::ios_base::fmtflags f);
+
+    template<typename charT, class traits, class Alloc>
+    mp_int(const std::basic_string<charT,traits,Alloc>& s, std::ios_base::fmtflags f);
+    
+    template<typename RandomAccessIterator>
+    mp_int(RandomAccessIterator first, RandomAccessIterator last, std::ios_base::fmtflags f);
+
+    mp_int(const mp_int& copy);
+
+    #ifdef BOOST_HAS_RVALUE_REFS
+    mp_int(mp_int&& copy);
+    #endif
+    
+    ~mp_int();
+
+    mp_int& operator = (const mp_int& rhs);
+
+    #ifdef BOOST_HAS_RVALUE_REFS
+    mp_int& operator = (mp_int&& rhs);
+    #endif
+    
+    template<typename IntegralT>
+    mp_int& operator = (IntegralT rhs);
+
+    mp_int& operator = (const char* s);
+    
+    mp_int& operator = (const wchar_t* s);
+
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator = (const std::basic_string<charT,traits,Alloc>& s);
+
+    void assign(const char* s, std::ios_base::fmtflags f);
+
+    void assign(const wchar_t* s, std::ios_base::fmtflags f);
+
+    template<typename charT, class traits, class Alloc>
+    void assign(const std::basic_string<charT,traits,Alloc>& s, std::ios_base::fmtflags f);  
+    
+    template<typename RandomAccessIterator>
+    void assign(RandomAccessIterator first, RandomAccessIterator last, std::ios_base::fmtflags f);
+
+    // modifiers
+    #ifdef BOOST_HAS_RVALUE_REFS
+    void swap(mp_int&& other);
+    #else
+    void swap(mp_int& other);
+    #endif
+
+    // increment/decrement
+    mp_int& operator ++();
+    mp_int& operator --();
+    mp_int  operator ++(int);
+    mp_int  operator --(int);
+
+    // shifting
+    mp_int& operator <<= (size_type);
+    mp_int& operator >>= (size_type);
+
+    // unary negate
+    mp_int& operator - ();
+
+    // arithmetic operators
+    mp_int& operator += (const mp_int& x);
+    mp_int& operator -= (const mp_int& x);
+    mp_int& operator *= (const mp_int& x);
+    mp_int& operator /= (const mp_int& x);
+    mp_int& operator %= (const mp_int& x);
+
+    // bitwise operators
+    mp_int& operator |= (const mp_int& x);
+    mp_int& operator &= (const mp_int& x);
+    mp_int& operator ^= (const mp_int& x);
+
+    // operators involving integral types
+    template<typename IntegralT> mp_int& operator += (IntegralT x);
+    template<typename IntegralT> mp_int& operator -= (IntegralT x);
+    template<typename IntegralT> mp_int& operator *= (IntegralT x);
+    template<typename IntegralT> mp_int& operator /= (IntegralT x);
+    template<typename IntegralT> mp_int& operator %= (IntegralT x);
+    template<typename IntegralT> mp_int& operator |= (IntegralT x);
+    template<typename IntegralT> mp_int& operator &= (IntegralT x);
+    template<typename IntegralT> mp_int& operator ^= (IntegralT x);
+
+    // operators involving char strings
+    mp_int& operator += (const char* s);
+    mp_int& operator -= (const char* s);
+    mp_int& operator *= (const char* s);
+    mp_int& operator /= (const char* s);
+    mp_int& operator %= (const char* s);
+    mp_int& operator |= (const char* s);
+    mp_int& operator &= (const char* s);
+    mp_int& operator ^= (const char* s);
+
+    // operators involving wchar_t strings
+    mp_int& operator += (const wchar_t* s);
+    mp_int& operator -= (const wchar_t* s);
+    mp_int& operator *= (const wchar_t* s);
+    mp_int& operator /= (const wchar_t* s);
+    mp_int& operator %= (const wchar_t* s);
+    mp_int& operator |= (const wchar_t* s);
+    mp_int& operator &= (const wchar_t* s);
+    mp_int& operator ^= (const wchar_t* s);
+
+    // operators involving std::basic_string
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator += (const std::basic_string<charT,traits,Alloc>& s);
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator -= (const std::basic_string<charT,traits,Alloc>& s);
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator *= (const std::basic_string<charT,traits,Alloc>& s);
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator /= (const std::basic_string<charT,traits,Alloc>& s);
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator %= (const std::basic_string<charT,traits,Alloc>& s);
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator |= (const std::basic_string<charT,traits,Alloc>& s);
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator &= (const std::basic_string<charT,traits,Alloc>& s);
+    template<typename charT, class traits, class Alloc>
+    mp_int& operator ^= (const std::basic_string<charT,traits,Alloc>& s);
+
+    // observers
+    allocator_type get_allocator() const;
+
+    bool is_even() const;
+    bool is_odd () const;
+
+    bool is_positive() const;
+    bool is_negative() const;
+
+    size_type precision() const;
+
+    operator unspecified_bool_type() const;
+
+    std::string to_string(std::ios_base::fmtflags f = std::ios_base::dec) const;
+
+    template<typename IntegralT>
+    IntegralT to_integral() const;
+
+    // low level access
+    typedef traits_type::digit_type digit_type;
+    typedef traits_type::word_type  word_type;
+
+    bool is_zero() const;
+
+    digit_type&       operator[](size_type i);
+    const digit_type& operator[](size_type i) const;
+    
+    digit_type&       at(size_type i);
+    const digit_type& at(size_type i) const;
+  };
+
+
+  // non-member functions
+
+  #ifdef BOOST_HAS_RVALUE_REFS
+  template<class A, class T>
+  void swap(mp_int<A,T>&&, mp_int<A,T>&&);
+  #else
+  void swap(mp_int<A,T>&, mp_int<A,T>&);
+  #endif
+
+  template<class A, class T>
+  mp_int<A,T> operator << (const mp_int<A,T>&, typename mp_int<A,T>::size_type);
+
+  template<class A, class T>
+  mp_int<A,T> operator >> (const mp_int<A,T>&, typename mp_int<A,T>::size_type);
+
+  template<class A, class T>
+  mp_int<A,T> operator - (const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator + (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator - (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator * (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator / (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator % (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator | (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator & (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator ^ (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator + (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator - (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator * (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator / (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator % (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator | (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator & (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator ^ (const mp_int<A,T>&, IntegralT);
+
+
+  // Comparison operators
+
+  template<class A, class T>
+  bool operator == (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator != (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator < (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator > (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator <= (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator >= (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  // Comparison between mp_int and std::basic_string
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator == (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator != (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator < (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator > (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator <= (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator >= (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  // Comparison between std::basic_string and mp_int
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator == (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator != (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator < (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator > (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator <= (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator >= (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  // Comparison between mp_int and const char*
+
+  template<class A, class T>
+  bool operator == (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator != (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator < (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator > (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator <= (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator >= (const mp_int<A,T>&, const char*);
+
+  // Comparison between const char* and mp_int
+
+  template<class A, class T>
+  bool operator == (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator != (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator < (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator > (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator <= (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator >= (const char*, const mp_int<A,T>&);
+
+  // Comparison between mp_int and const wchar_t*
+
+  template<class A, class T>
+  bool operator == (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator != (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator < (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator > (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator <= (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator >= (const mp_int<A,T>&, const wchar_t*);
+
+  // Comparison between const wchar_t* and mp_int
+
+  template<class A, class T>
+  bool operator == (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator != (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator < (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator > (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator <= (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator >= (const wchar_t*, const mp_int<A,T>&);
+
+  // Comparison between mp_int and integral type
+
+  template<class A, class T, typename IntegralT>
+  bool operator == (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator != (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator < (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator > (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator <= (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator >= (const mp_int<A,T>&, IntegralT);
+
+  // Comparison between integral type and mp_int
+
+  template<class A, class T, typename IntegralT>
+  bool operator == (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator != (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator < (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator > (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator <= (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator >= (IntegralT, const mp_int<A,T>&);
+
+
+  // Stream I/O
+
+  template<class A, class T, typename charT, class traits>
+  std::basic_istream<charT, traits>&
+  operator >> (std::basic_istream<charT, traits>& is, mp_int<A,T>& x);
+
+  template<class A, class T, typename charT, class traits>
+  std::basic_ostream<charT, traits>&
+  operator << (std::basic_ostream<charT, traits>& os, const mp_int<A,T>& x);
+
+
+  // Special functions
+
+  template<class A, class T>
+  mp_int<A,T> abs(const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> gcd(const mp_int<A,T>& a, const mp_int<A,T>& b);
+
+  template<class A, class T>
+  mp_int<A,T> lcm(const mp_int<A,T>& a, const mp_int<A,T>& b);
+
+  template<class A, class T>
+  int jacobi(const mp_int<A,T>& a, const mp_int<A,T>& p);
+
+  template<class A, class T>
+  mp_int<A,T> pow(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n);
+
+  template<class A, class T>
+  mp_int<A,T> modpow(const mp_int<A,T>& base, const mp_int<A,T>& exp, const mp_int<A,T>& mod);
+
+  template<class A, class T>
+  mp_int<A,T> sqrt(const mp_int<A,T>& x);
+
+  template<class A, class T>
+  mp_int<A,T> nth_root(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n);
+
+
+  } // namespace mp_math
+  } // namespace boost
+
+
+[h3 Construction from / assignment to a string object]
+In a constructor or assignment operation without the possibility to specify the base
+of the string argument the base of the number is deduced from the string. If the
+string starts with `0x` or `0X` then the number will be treated as hexadecimal
+value. If the string starts with `0` then the number will be treated as octal
+value else it will be treated as decimal value. An optional `-` sign is allowed
+as the first character in the string to indicate a negative value.
+
+In a constructor or assignment operation with the ability to specify the format
+of the string argument via a `std::ios_base::fmtflags` parameter, possible
+formatting flags are:
+
+* `std::ios_base::showbase`
+* `std::ios_base::dec`
+* `std::ios_base::hex`
+* `std::ios_base::oct`
+
+
+[heading Construct/Copy/Destroy/Assign]
+
+  mp_int();
+
+* [*Effects:] Constructs an empty `mp_int` object, such an uninitialized
+`mp_int` has no value, i.e. it is /not/ zero.
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  template<typename IntegralT>
+  mp_int(IntegralT x, typename enable_if<boost::is_integral<IntegralT> >::type* dummy = 0);
+
+* [*Effects:] Constructs an `mp_int` object from an integral type. The value of
+the object is that of the integral type.
+* [*Complexity:] O(N) where N is the number of bits of IntegralT.
+* [*Throws: ] `std::bad_alloc`.
+
+
+  mp_int(const char* s);
+  mp_int(const wchar_t* s);
+
+* [*Requires: ] `s` points to a valid number formatted as string or to an empty
+string.
+* [*Effects:] Constructs an `mp_int` object from a string.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<typename charT, class traits, class Alloc>
+  mp_int(const std::basic_string<charT,traits,Alloc>& s);
+
+* [*Requires: ] `s` contains a valid number formatted as string or `s` is an
+empty string.
+* [*Effects:] Constructs an `mp_int` object from a string.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<typename RandomAccessIterator>
+  mp_int(RandomAccessIterator first, RandomAccessIterator last);
+
+* [*Requires: ] `first` and `last` are iterators into a string.
+* [*Effects:] Constructs an `mp_int` object from two iterators.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  mp_int(const char* s, std::ios_base::fmtflags f);
+  mp_int(const wchar_t* s, std::ios_base::fmtflags f);
+
+* [*Requires: ] `s` points to a valid number formatted according to the flags in
+`f` or `s` is an empty string.
+* [*Effects:] Constructs an `mp_int` object from a string.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character or if an
+    unrecognized formatting flag was set.
+
+
+  template<typename charT, class traits, class Alloc>
+  mp_int(const std::basic_string<charT,traits,Alloc>& s, std::ios_base::fmtflags f);
+
+* [*Requires: ] `s` contains a valid number formatted according to the flags in
+`f` or `s` is an empty string.
+* [*Effects:] Constructs an `mp_int` object from a string.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character or if an
+    unrecognized formatting flag was set.
+
+
+  template<typename RandomAccessIterator>
+  mp_int(RandomAccessIterator first, RandomAccessIterator last, std::ios_base::fmtflags f);
+
+* [*Requires: ] `first` and `last` are iterators into a string formatted
+according to the formatting flags in `f`.
+* [*Effects:] Constructs an `mp_int` object from two iterators.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character or if an
+    unrecognized formatting flag was set.
+
+
+  mp_int(const mp_int& copy);
+
+* [*Effects:] Constructs a copy of a given `mp_int`.
+* [*Complexity:] O(N), where N is the number of digits in `copy`.
+* [*Throws: ] `std::bad_alloc`.
+
+  
+  mp_int(mp_int&& copy);
+
+* [*Effects:] Constructs an `mp_int` by moving `copy` into `*this`.
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+  
+
+  ~mp_int();
+
+* [*Effects:] Destroys `*this`.
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  mp_int& operator = (const mp_int& rhs);
+
+* [*Effects:] Copies the value of `rhs` into `*this`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+  
+  mp_int& operator = (mp_int&& rhs);
+
+* [*Effects: ] `*this` obtains the value of `rhs`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  template<typename IntegralT>
+  mp_int& operator = (IntegralT rhs);
+
+* [*Effects: ] `*this` obtains the value of `rhs`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] basic.
+
+  mp_int& operator = (const char* s);
+  mp_int& operator = (const wchar_t* s);
+
+* [*Requires: ] `s` points to a valid number formatted as string or to an empty
+string.
+* [*Effects:] `*this = mp_int(s);`.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+* [*Exception safety:] basic.
+
+
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator = (const std::basic_string<charT,traits,Alloc>& s);
+
+* [*Requires: ] `s` points to a valid number formatted as string or to an empty
+string.
+* [*Effects:] `*this = mp_int(s);`.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+* [*Exception safety:] basic.
+
+
+  void assign(const char* s, std::ios_base::fmtflags f);
+  void assign(const wchar_t* s, std::ios_base::fmtflags f);
+
+* [*Requires: ] `s` points to a valid number formatted according to the flags in
+`f` or `s` is an empty string.
+* [*Effects:] Constructs an `mp_int` object from a string.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character or if an
+    unrecognized formatting flag was set.
+* [*Exception safety:] basic.
+
+
+  template<typename charT, class traits, class Alloc>
+  void assign(const std::basic_string<charT,traits,Alloc>& s, std::ios_base::fmtflags f);  
+
+* [*Requires: ] `s` contains a valid number formatted according to the flags in
+`f` or `s` is an empty string.
+* [*Effects:] Constructs an `mp_int` object from a string.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character or if an
+    unrecognized formatting flag was set.
+* [*Exception safety:] basic.
+
+
+  template<typename RandomAccessIterator>
+  void assign(RandomAccessIterator first, RandomAccessIterator last, std::ios_base::fmtflags f);
+
+* [*Requires: ] `first` and `last` are iterators into a string formatted
+according to the formatting flags in `f`.
+* [*Effects:] Constructs an `mp_int` object from two iterators.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character or if an
+    unrecognized formatting flag was set.
+* [*Exception safety:] basic.
+
+
+[heading Modifiers]
+
+  void swap(mp_int&& other);
+
+* [*Effects:] Swaps the value of `other` and `*this`.
+* [*Complexity:] O(1).
+* [*Exception safety:] nothrow.
+
+
+  void swap(mp_int& other);
+
+* [*Effects:] Swaps the value of `other` and `*this`.
+* [*Complexity:] O(1).
+* [*Exception safety:] nothrow.
+
+
+[heading Increment/decrement]
+
+  mp_int& operator ++();
+
+* [*Effects:]
+``
+*this += 1;
+return *this;
+``
+* [*Returns: ] `*this`.
+* [*Complexity:] best case is O(1), worst case is O(N) - this happens when the
+addition causes a carry bit to ripple through all digits subsequently.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  mp_int& operator --();
+
+* [*Effects:]
+``
+*this -= 1;
+return *this;
+``
+* [*Returns: ] `*this`.
+* [*Complexity:] best case is O(1), worst case is O(N) - this happens when the
+subtraction causes a borrow bit to ripple through all digits subsequently.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  mp_int  operator ++(int);
+
+* [*Effects:]
+``
+mp_int tmp(*this);
+*this += 1;
+return tmp;
+``
+* [*Returns:] The value of `*this` before incrementation.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  mp_int  operator --(int);
+
+* [*Effects:]
+``
+mp_int tmp(*this);
+*this -= 1;
+return tmp;
+``
+* [*Returns:] The value of `*this` before decrementation.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+[heading Shifting]
+
+ mp_int& operator <<= (size_type x);
+
+* [*Effects:] Shift `*this` by `x` bits to the left.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+ mp_int& operator >>= (size_type x);
+
+* [*Effects:] Shift `*this` by `x` bits to the right.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+[heading Unary negate]
+
+  mp_int& operator - ();
+
+* [*Effects:] Negates `*this`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(1).
+* [*Exception safety:] nothrow.
+
+
+[heading Arithmetic operators]
+
+  mp_int& operator += (const mp_int& x);
+
+* [*Effects:] Adds `x` to `*this`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  mp_int& operator -= (const mp_int& x);
+
+
+* [*Effects:] Subtracts `x` from `*this`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  mp_int& operator *= (const mp_int& x);
+
+* [*Effects:] Multiplies `*this` by `x`.
+* [*Returns: ] `*this`.
+* [*Complexity:] If `&x == this` then a squaring algorithm will be used.
+Different multiplication algorithms are chosen for numbers of different size.
+The thresholds can be tuned via the `mp_int_traits` class template parameter.
+  * Small numbers: Comba algorithm O(N^2).
+  * Midsize numbers: Karatsuba algorithm O(N^log2(3)) ~ O(N^1.585).
+  * Large numbers: Toom-Cook algorithm O(N^(log(5)/log(3))) ~ O(N^1.465).
+
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+ mp_int& operator /= (const mp_int& x);
+
+* [*Requires: ] `x != 0`. 
+* [*Effects:] Divides `*this` by `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ]
+  * `std::bad_alloc`
+  * `std::domain_error` if `x == 0`.
+
+* [*Exception safety:] strong.
+
+
+ mp_int& operator %= (const mp_int& x);
+
+* [*Requires: ] `x != 0`. 
+* [*Effects:] Modulus `*this` by `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ]
+  * `std::bad_alloc`
+  * `std::domain_error` if `x == 0`.
+
+* [*Exception safety:] strong.
+
+
+[heading Bitwise operators]
+
+  mp_int& operator |= (const mp_int& x);
+
+* [*Effects: ] `*this` OR `x`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  mp_int& operator &= (const mp_int& x);
+
+* [*Effects: ] `*this` AND `x`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  mp_int& operator ^= (const mp_int& x);
+
+* [*Effects: ] `*this` XOR `x`.
+* [*Returns: ] `*this`.
+* [*Complexity:] O(N).
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+[heading Operators involving integral types]
+
+  template<typename IntegralT> mp_int& operator += (IntegralT x);
+
+* [*Effects:] Adds `x` to `*this`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT> mp_int& operator -= (IntegralT x);
+
+* [*Effects:] Subtracts `x` to `*this`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT> mp_int& operator *= (IntegralT x);
+
+* [*Effects:] Multiplies `*this` by `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT> mp_int& operator /= (IntegralT x);
+
+* [*Effects:] Divides `*this` by `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT> mp_int& operator %= (IntegralT x);
+
+* [*Effects: ] `*this` modulo `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT> mp_int& operator |= (IntegralT x);
+
+* [*Effects:] Applies the bitwise or operation on `*this` and the absolute of `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT> mp_int& operator &= (IntegralT x);
+
+* [*Effects:] Applies the bitwise and operation on `*this` and the absolute of `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT> mp_int& operator ^= (IntegralT x);
+
+* [*Effects:] Applies the bitwise xor operation on `*this` and the absolute of `x`.
+* [*Returns: ] `*this`.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+[heading Operators involving char/wchar_t strings]
+
+  mp_int& operator += (const char* s);
+  mp_int& operator += (const wchar_t* s);
+  mp_int& operator -= (const char* s);
+  mp_int& operator -= (const wchar_t* s);
+  mp_int& operator *= (const char* s);
+  mp_int& operator *= (const wchar_t* s);
+  mp_int& operator /= (const char* s);
+  mp_int& operator /= (const wchar_t* s);
+  mp_int& operator %= (const char* s);
+  mp_int& operator %= (const wchar_t* s);
+  mp_int& operator |= (const char* s);
+  mp_int& operator |= (const wchar_t* s);
+  mp_int& operator &= (const char* s);
+  mp_int& operator &= (const wchar_t* s);
+  mp_int& operator ^= (const char* s);
+  mp_int& operator ^= (const wchar_t* s);
+
+[heading Operators involving std::basic_string]
+
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator += (const std::basic_string<charT,traits,Alloc>& s);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator -= (const std::basic_string<charT,traits,Alloc>& s);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator *= (const std::basic_string<charT,traits,Alloc>& s);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator /= (const std::basic_string<charT,traits,Alloc>& s);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator %= (const std::basic_string<charT,traits,Alloc>& s);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator |= (const std::basic_string<charT,traits,Alloc>& s);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator &= (const std::basic_string<charT,traits,Alloc>& s);
+  template<typename charT, class traits, class Alloc>
+  mp_int& operator ^= (const std::basic_string<charT,traits,Alloc>& s);
+
+
+[heading Observers]
+
+  allocator_type get_allocator() const;
+
+* [*Returns: ] A copy of the allocator.
+* [*Complexity:] O(1).
+* [*Throws:] Nothing if allocator copy constructor is nothrow.
+
+
+  bool is_even() const;
+
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  bool is_odd () const;
+
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  bool is_positive() const;
+
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  bool is_negative() const;
+
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  size_type precision() const;
+
+* [*Returns:] The number of bits used by the absolute value of *this.
+* [*Complexity:] O(N).
+* [*Throws:] Nothing.
+
+  operator unspecified_bool_type() const;
+
+* [*Returns: ] `*this != 0`.
+* [*Complexity:] O(1).
+* [*Throws:] Nothing.
+
+
+  std::string to_string(std::ios_base::fmtflags f = std::ios_base::dec) const;
+
+* [*Effects:] Converts `*this` to a `std::string`, formatting of the string is
+done according to the `std::ios_base::fmtflags` parameter. Possible formatting
+flags are:
+  * `std::ios_base::showpos`
+  * `std::ios_base::showbase`
+  * `std::ios_base::dec`
+  * `std::ios_base::hex`
+  * `std::ios_base::oct`
+  * `std::ios_base::uppercase`
+
+* [*Returns: ] `*this` converted to a `std::string` object.
+* [*Throws: ] `std::bad_alloc`.
+* [*Exception safety:] strong.
+
+
+  template<typename IntegralT>
+  IntegralT to_integral() const;
+
+* [*Returns: ] `*this` converted to an object of type `IntegralT`.
+* [*Complexity:] O(1).
+* [*Throws: ] `std::overflow_error` if `IntegralT` does not have enough
+precision to hold the result.
+* [*Exception safety:] strong.
+
+
+
+[heading Non-member functions]
+
+  template<class A, class T>
+  void swap(mp_int<A,T>&&, mp_int<A,T>&&);
+
+  template<class A, class T>
+  mp_int<A,T> operator << (const mp_int<A,T>&, typename mp_int<A,T>::size_type);
+
+  template<class A, class T>
+  mp_int<A,T> operator >> (const mp_int<A,T>&, typename mp_int<A,T>::size_type);
+
+  template<class A, class T>
+  mp_int<A,T> operator - (const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator + (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator - (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator * (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator / (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator % (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator | (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator & (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  mp_int<A,T> operator ^ (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator + (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator - (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator * (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator / (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator % (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator | (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator & (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  mp_int<A,T> operator ^ (const mp_int<A,T>&, IntegralT);
+
+These functions are implemented in terms of their respective member functions.
+
+
+[heading Comparison operators]
+
+  template<class A, class T>
+  bool operator == (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator != (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator < (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator > (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator <= (const mp_int<A,T>&, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator >= (const mp_int<A,T>&, const mp_int<A,T>&);
+
+* [*Effects:] These operators compare the numeric value of their arguments and
+return a truth value based on that evaluation.
+* [*Throws:] Nothing.
+
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator == (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator != (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator < (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator > (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator <= (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator >= (const mp_int<A,T>&, const std::basic_string<charT,Traits,Alloc>&);
+
+* [*Effects:] Converts the string argument to an `mp_int` object and compares it
+to the object on the left side of the expression.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator == (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator != (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator < (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator > (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator <= (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+  template<class A, class T, class charT, class Traits, class Alloc>
+  bool operator >= (const std::basic_string<charT,Traits,Alloc>&, const mp_int<A,T>&);
+
+* [*Effects:] Converts the string argument to an `mp_int` object and compares it
+to the object on the right side of the expression.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<class A, class T>
+  bool operator == (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator != (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator < (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator > (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator <= (const mp_int<A,T>&, const char*);
+
+  template<class A, class T>
+  bool operator >= (const mp_int<A,T>&, const char*);
+
+* [*Effects:] Converts the string argument to an `mp_int` object and compares it
+to the object on the left side of the expression.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<class A, class T>
+  bool operator == (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator != (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator < (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator > (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator <= (const char*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator >= (const char*, const mp_int<A,T>&);
+
+* [*Effects:] Converts the string argument to an `mp_int` object and compares it
+to the object on the right side of the expression.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<class A, class T>
+  bool operator == (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator != (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator < (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator > (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator <= (const mp_int<A,T>&, const wchar_t*);
+
+  template<class A, class T>
+  bool operator >= (const mp_int<A,T>&, const wchar_t*);
+
+* [*Effects:] Converts the string argument to an `mp_int` object and compares it
+to the object on the left side of the expression.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<class A, class T>
+  bool operator == (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator != (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator < (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator > (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator <= (const wchar_t*, const mp_int<A,T>&);
+
+  template<class A, class T>
+  bool operator >= (const wchar_t*, const mp_int<A,T>&);
+
+* [*Effects:] Converts the string argument to an `mp_int` object and compares it
+to the object on the right side of the expression.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::invalid_argument` if the string contains an invalid character.
+
+
+  template<class A, class T, typename IntegralT>
+  bool operator == (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator != (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator < (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator > (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator <= (const mp_int<A,T>&, IntegralT);
+
+  template<class A, class T, typename IntegralT>
+  bool operator >= (const mp_int<A,T>&, IntegralT);
+
+* [*Effects:] Converts the integral argument to an `mp_int` object and compares it
+to the object on the left side of the expression.
+* [*Throws: ] `std::bad_alloc`.
+
+
+  template<class A, class T, typename IntegralT>
+  bool operator == (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator != (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator < (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator > (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator <= (IntegralT, const mp_int<A,T>&);
+
+  template<class A, class T, typename IntegralT>
+  bool operator >= (IntegralT, const mp_int<A,T>&);
+
+* [*Effects:] Converts the integral argument to an `mp_int` object and compares it
+to the object on the right side of the expression.
+* [*Throws: ] `std::bad_alloc`.
+
+
+[heading Stream I/O]
+
+  template<class A, class T, typename charT, class traits>
+  std::basic_istream<charT, traits>&
+  operator >> (std::basic_istream<charT, traits>& is, mp_int<A,T>& x);
+
+  template<class A, class T, typename charT, class traits>
+  std::basic_ostream<charT, traits>&
+  operator << (std::basic_ostream<charT, traits>& os, const mp_int<A,T>& x);
+
+
+[heading Special functions]
+
+  template<class A, class T>
+  mp_int<A,T> abs(const mp_int<A,T>& x);
+
+* [*Returns:] The positive value of `x`.
+* [*Complexity:] O(1).
+* [*Throws: ] `std::bad_alloc`.
+
+
+  template<class A, class T>
+  mp_int<A,T> gcd(const mp_int<A,T>& a, const mp_int<A,T>& b);
+
+* [*Returns:] The greatest common divisor of `a` and `b`.
+* [*Complexity:] O((log2(AB))^2).
+* [*Throws: ] `std::bad_alloc`.
+
+
+  template<class A, class T>
+  mp_int<A,T> lcm(const mp_int<A,T>& a, const mp_int<A,T>& b);
+
+* [*Returns:] The least common multiple of `a` and `b`.
+* [*Complexity:] O((log2(AB))^2).
+* [*Throws: ] `std::bad_alloc`.
+
+
+  template<class A, class T>
+  int jacobi(const mp_int<A,T>& a, const mp_int<A,T>& p);
+
+* [*Returns:] The Jacobi symbol of integer `a` and positive odd integer `p`.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::domain_error` if `p` is negative.
+
+
+  template<class A, class T>
+  mp_int<A,T> pow(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n);
+
+* [*Returns:] The `n`th power of `x`.
+* [*Throws: ] `std::bad_alloc`.
+
+
+  template<class A, class T>
+  mp_int<A,T> modpow(const mp_int<A,T>& base,
+                     const mp_int<A,T>& exp,
+                     const mp_int<A,T>& mod);
+
+
+* [*Returns: ] `(base ^ exp) % mod`.
+* [*Throws: ] `std::bad_alloc`.
+
+
+  template<class A, class T>
+  mp_int<A,T> sqrt(const mp_int<A,T>& x);
+
+* [*Returns:] The square root of `x`.
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::domain_error` if `x` is negative.
+
+
+  template<class A, class T>
+  mp_int<A,T> nth_root(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n);
+
+* [*Returns:] The `n`th root of `x`.
+* [*Complexity:] O(log(N)).
+* [*Throws:]
+  * `std::bad_alloc`
+  * `std::domain_error` if `x` is negative and `n` is odd.
+
+
+[endsect][/mp_int reference]
+
Added: sandbox/mp_math/libs/mp_math/doc/mp_int_traits_reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/mp_int_traits_reference.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,37 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section mp_int_traits reference]
+
+The second template parameter to mp_int is a type which allows to customize some
+of mp_int's internal workings.
+
+[heading Synopsis]
+``
+// <boost/mp_math/mp_int/traits.hpp>
+namespace boost {
+namespace mp_math {
+
+template<
+  typename Digit = implementation defined,
+  typename Word = implementation defined
+>
+struct mp_int_traits
+{
+  typedef std::size_t size_type;
+  typedef Digit       digit_type;
+  typedef Word        word_type;
+
+  static size_type toom_mul_cutoff;           // default: 350
+  static size_type toom_sqr_cutoff;           // default: 400
+  static size_type karatsuba_mul_cutoff;      // default: 80
+  static size_type karatsuba_sqr_cutoff;      // default: 120
+};
+
+} // namespace mp_math
+} // namespace boost
+``
+[endsect][/mp_int_traits reference]
+
Added: sandbox/mp_math/libs/mp_math/doc/performance.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/performance.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,130 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section Performance]
+
+[section Tips]
+
+* A statement like
+``x = a + b;``
+involves the creation of a temporary `mp_int` inside `operator +` because it is
+not able to write the result directly into `x` which may already have enough
+memory allocated to hold the result. Instead rewrite it into
+``
+x = a;
+x += b;
+``
+This trick proves to be useful only for simple operations like addition and
+subtraction.
+* In operations involving built in integral types, try to use unsigned types,
+preferrably unsigned types that are as large or smaller than
+mp_int<>::digit_type.
+* Use hexadecimal digits for input and output. Conversion from/to power of two
+bases uses a O(n) algorithm which is not possible for base 10.
+
+[endsect][/Tips]
+
+
+
+
+[section Measurements]
+
+A benchmark program is supplied with Boost.Mp_math under libs\/mp_math\/tools\/benchmark.
+This benchmark compares some primitive operations of different multi precision
+integer libraries. It creates detailed result files and uses
+[@http://www.gnuplot.info/ gnuplot] to create graphs.
+
+Example invocations:
+[pre
+'''benchmark''' // runs all benches
+'''benchmark --help'''
+'''benchmark --ops="add subtract multiply" --libs="boost.mp_math libtommath"'''
+]
+
+
+[section AMD Athlon XP 2000+]
+
+[pre
+'''Operating System: Arch Linux (i686), Kernel 2.6.26, glibc 2.8'''
+'''Compiler: gcc-4.3.2'''
+]
+Libraries being compared:
+
+* Boost.Mp_math-1_37
+  * switches used: -ftemplate-depth-128 -O3 -finline-functions -march=i686 -mtune=generic -std=c++0x
+* libtommath-0.41
+  * switches used: -ftemplate-depth-128 -O3 -finline-functions -march=i686 -mtune=generic
+* gmp-4.2.2 (precompiled distribution package, uses generic i386 asm and Intel
+  P6 (Pentium Pro) asm where available)
+  * switches used: -march=i686 -mtune=generic -O2
+
+[h3 Input vectors]
+Operand size is measured in number of bits.
+I chose to vary the operand size for the benchmarks a little to see how well the
+operation handles inputs of differing sizes. Benchmarks that use only one
+operand use operand 1.
+[$benchmark_imgs/k7/input_vecs.png]
+
+While input operand 1 grows linearly, input operand 2's size is
+determined by a modified sine function.
+
+
+[h3 Construct from decimal string]
+[$benchmark_imgs/k7/ctor_dec.png]
+
+
+[h3 Construct from hex string]
+[$benchmark_imgs/k7/ctor_hex.png]
+
+
+[h3 Conversion to decimal string]
+[$benchmark_imgs/k7/to_dec.png]
+
+
+[h3 Conversion to hex string]
+[$benchmark_imgs/k7/to_hex.png]
+
+
+[h3 Add]
+[$benchmark_imgs/k7/add.png]
+
+
+[h3 Subtract]
+[$benchmark_imgs/k7/subtract.png]
+
+
+[h3 Multiply]
+[$benchmark_imgs/k7/multiply.png]
+
+
+[h3 Divide]
+[$benchmark_imgs/k7/divide.png]
+
+
+[h3 Modulo]
+[$benchmark_imgs/k7/modulo.png]
+
+
+[h3 Square]
+[$benchmark_imgs/k7/square.png]
+
+
+[h3 Modular Power]
+The operation looks like this: `dest = (op1 ^ op1) % op2`.
+This graph uses a logarithmic scale.
+[$benchmark_imgs/k7/modpow.png]
+
+
+[endsect][/AMD K7 Thunderbird 800Mhz]
+
+
+
+[endsect][/Measurements]
+
+
+
+
+
+[endsect][/Performance]
Added: sandbox/mp_math/libs/mp_math/doc/primality_tests_reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/primality_tests_reference.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,136 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section Primality Tests reference]
+
+[section primality_division_test]
+
+This function object tests a candidate `p` by repeatedly dividing it by small
+primes (2, 3, 5, 7, 11...). This is a test that should be used before other more
+complex tests because it quickly sieves out composite numbers. For example,
+testing for 2, 5, 7 will eliminate 54% of all numbers, testing for all primes
+less than 100 eliminates 70%, for all primes less than 256 it is 80%.
+
+[heading Synopsis]
+
+  // <boost/mp_math/mp_int.hpp>
+  struct primality_division_test
+  {
+    typedef bool result_type;
+
+    template<class A, class T>
+    bool operator()(const mp_int<A,T>& p) const;
+  };
+
+
+[h3 Members]
+
+  template<class A, class T>
+  bool operator()(const mp_int<A,T>& p) const;
+
+* [*Effects:] Returns true if `p` is probably prime. Returns false if `p`
+is definitely composite.
+
+[endsect][/primality_division_test]
+
+
+[section primality_fermat_test]
+
+This test is based on Fermat's little theorem which states that if an integer
+`p` is prime, then for all integers `a` where 0 < `a` < `p`
+
+`a**(p-1) = 1 (mod p)`
+
+an alternative formulation is
+
+`a**p = a (mod p)`
+
+For each round the test creates a random base `a` and checks if the condition
+holds.
+There is a class of pseudoprimes called carmichael numbers which are less likely
+though not impossible with enough rounds to be detected by this test.
+
+[heading Synopsis]
+
+  // <boost/mp_math/mp_int.hpp>
+  template<class Distribution = uniform_mp_int<> >
+  struct primality_fermat_test
+  {
+    typedef Distribution distribution_type;
+    typedef bool         result_type;
+
+    explicit primality_fermat_test(unsigned int rounds);
+
+    template<class Engine, class A, class T>
+    bool operator()(Engine& e, const mp_int<A,T>& p) const;
+  };
+
+
+[h3 Members]
+
+  explicit primality_fermat_test(unsigned int r);
+
+* [*Effects:] Constructs a `primality_fermat_test` object with the number
+of test rounds given by `r`.
+
+  template<class Engine, class A, class T>
+  bool operator()(Engine& e, const mp_int<A,T>& p) const;
+
+* [*Effects:] Returns true if `p` is probably prime. Returns false if `p`
+is definitely composite.
+
+[endsect][/primality_fermat_test]
+
+
+[section primality_miller_rabin_test]
+
+This test is an improved version of the Fermat primality test that will also
+detect carmichael numbers.
+
+[heading Synopsis]
+
+  // <boost/mp_math/mp_int.hpp>
+  template<class Distribution = uniform_mp_int<> >
+  struct primality_miller_rabin_test
+  {
+    typedef Distribution distribution_type;
+    typedef bool         result_type;
+
+    explicit primality_miller_rabin_test(unsigned int r = 0);
+
+    template<class Engine, class A, class T>
+    bool operator()(Engine& e, const mp_int<A,T>& p) const;
+
+    static unsigned int recommended_number_of_rounds(unsigned bits);
+  };
+
+
+[h3 Members]
+
+  explicit primality_miller_rabin_test(unsigned int r = 0);
+
+* [*Effects:] Constructs a `primality_miller_rabin_test` object with the number
+of test rounds given by `r`. If `r == 0` then each invocation of this function
+object will use the recommended number of rounds.
+
+  template<class Engine, class A, class T>
+  bool operator()(Engine& e, const mp_int<A,T>& p) const;
+
+* [*Requires:] `p` is odd.
+* [*Effects:] Returns true if `p` is probably prime. Returns false if `p`
+is definitely composite.
+
+
+  unsigned int recommended_number_of_rounds(unsigned bits);
+
+* [*Effects:] Returns the recommended number of rounds for a number of precision
+`bits` so that the probability of error is less than 2^-96.
+
+[endsect][/primality_miller_rabin_test]
+
+
+
+[endsect][/uniform_mp_int_bits reference]
+
Added: sandbox/mp_math/libs/mp_math/doc/tutorial.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/tutorial.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,208 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section Tutorial]
+
+
+[section General use]
+
+The only header you need to include to use the library is
+`<boost/mp_math/mp_int.hpp>`. This is a header-only library so deployment is easy.
+All functions and objects of this library live in namespace `boost::mp_math`.
+
+  #include <iostream>
+  #include <string>
+  #include <boost/mp_math/mp_int.hpp>
+
+  using namespace boost::mp_math;
+  using namespace std;
+
+  int main()
+  {
+    // init from string
+    mp_int<> x("93423894782394782347823947289374");
+    // init from integral type
+    mp_int<> y = 2340;
+    mp_int<> z = x * y;
+
+    // stream output reacts to stream flags
+    cout << hex << z << endl;
+
+    // automatic detection of radix using the base prefix 0x
+    z = "0xaaaabbbbccccddddeeeeffff222255557777";
+    
+    z /= y;
+
+    // explicit conversion to string according to formatting flags
+    string s = z.to_string<string>(ios::hex | ios::showbase);
+    cout << s << endl;
+
+    z -= z;
+
+    // explicit conversion to built in integral types - this will throw
+    // std::overflow_error if int does not have enough precision to hold the
+    // result
+    int result = z.to_integral<int>();
+    
+    return result;
+  }
+
+In most cases the `mp_int` type will behave like a built in integral type.
+
+[endsect][/General use]
+
+
+[section Random number generation]
+
+The random number generators have interfaces similar to Boost.Random. Including
+`<boost/random.hpp>` is not necessary because it is used internally by the
+`mp_int` random machinery. The random number engine `mt19937` that we use from
+here on lives in namespace `boost`.
+
+
+  const mp_int<> min(0U);
+  const mp_int<> max("0x8974651231456456564");
+  
+  uniform_mp_int<> generator(min, max);
+  
+  // Choose a random number engine.
+  mt19937 e;
+
+  // Now generate a random number.
+  mp_int<> r = generator(e);
+
+
+Another probably more useful alternative is to generate random numbers of a
+certain precision measured in bits.
+
+
+  // A generator for 2048 bit integers.
+  uniform_mp_int_bits<> generator(2048);
+
+  mt19937 e;
+  mp_int<> r = generator(e);
+
+Note that the numbers will always be 2048 bits large, i.e. the 2048th bit is
+always set to 1.
+
+[endsect][/Random number generation]
+
+
+
+[section Primality testing]
+
+Currently all primality tests in this library are probabilistic. A probabilistic
+primality test cannot ascertain that a prime candidate p is really prime. It can
+however ascertain that it is a composite number.
+
+Here we will learn how to test a number `p` for primality using the fermat
+primality test. We use boost::bind to bind the random number engine to the test
+functor. That is necessary because the test functor's function invocation
+operator needs the random number engine. The operator looks like this:
+
+  bool operator()(Engine& e, const mp_int<>& p) const;
+
+We need to bind the random number engine to the first parameter slot. Let's do
+it!
+
+  // Create the fermat test functor with 4 rounds of testing.
+  primality_fermat_test<> test(4);
+
+  // Create a random number engine.
+  mt19937 rng;
+
+  // Create a random 1024 bit candidate number.
+  mp_int<> p = uniform_mp_int_bits<>(1024)(rng);
+
+  bool is_p_prime = is_prime(p, bind(test, rng, _1));
+
+
+[endsect][/Primality testing]
+
+
+
+[section Prime number generation]
+
+
+[section prime_generator]
+
+First we will look at how to generate prime numbers using a simple trial
+division test. What this means is that the prime generator creates a random
+number and then repeatedly divides it by small primes until it finds a number
+that passes this test.
+
+  // Create a generator for 2048 bit primes.
+  prime_generator<primality_division_test> generator(2048);
+
+  // Create a random number engine.
+  mt19937 rng;
+
+  // Now create a prime.
+  mp_int<> prime = generator(rng);
+
+
+[endsect][/prime_generator]
+
+
+[section safe_prime_generator]
+
+A safe prime is a prime `p` for which `(p-1)/2` is also prime. Such prime numbers
+are much rarer and thus take longer to generate.
+
+Now we will look at how to use a more sophisticated primality test like
+`primality_miller_rabin_test` for prime number generation. It is very useful to
+combine this test with the `primality_division_test`. This will involve a bit of
+code, mostly because `primality_miller_rabin_test` and `safe_prime_generator`
+require a random number generator. The latter needs randomness to create a
+candidate to test for primality and the miller rabin test needs randomness to
+test the candidate effectively.
+
+  // Define a function object that checks a prime candidate p first with a trial
+  // division and then with the miller-rabin algorithm. For ease of use we give
+  // it default template arguments.
+  // It does not hold a reference to the random number engine because that could
+  // lead to lifetime problems.
+  template<
+    class Engine = mt19937,
+    class Distribution = uniform_mp_int_bits<>
+  >
+  struct primality_test
+  {
+    primality_division_test                   test1;
+    primality_miller_rabin_test<Distribution> test2;
+    Engine rng;
+
+    explicit tester(const Engine& e = Engine()) : rng(e) {}
+
+    bool operator()(const mp_int<>& p)
+    {
+      return test1(p) && test2(rng, p);
+    }
+  };
+
+  // Create a random number engine that we will feed to the different
+  // algorithms.
+  mt19937 rng;
+
+  // Create a generator for safe primes with 128 bits precision.
+  typedef safe_prime_generator<primality_test<>, uniform_mp_int_bits<> >
+    generator_type;
+  
+  generator_type generator(128, primality_test<>(rng));
+
+  mp_int<> prime = generator(rng);
+
+Remember, the generated numbers are ['probably] prime.
+
+[endsect][/safe_prime_generator]
+
+
+
+[endsect][/Prime number generation]
+
+
+
+[endsect][/Tutorial]
+
Added: sandbox/mp_math/libs/mp_math/doc/uniform_mp_int_bits_reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/uniform_mp_int_bits_reference.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,60 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section uniform_mp_int_bits reference]
+
+[heading Synopsis]
+
+  // <boost/mp_math/mp_int.hpp>
+  template<class MpInt = mp_int<> >
+  struct uniform_mp_int_bits
+  {
+    typedef MpInt input_type;
+    typedef MpInt result_type;
+
+    static const bool has_fixed_range = false;
+
+    uniform_mp_int_bits(typename MpInt::size_type bits);
+
+    result_type min() const;
+    result_type max() const;
+
+    void reset();
+    
+    template<class UniformRandomNumberGenerator>
+    result_type operator()(UniformRandomNumberGenerator& urng);
+  };
+
+
+[h3 Members]
+
+  uniform_mp_int_bits(typename MpInt::size_type x);
+
+* [*Effects:] Constructs a `uniform_mp_int_bits` object. All numbers generated
+by this object will be `x` bits in size.
+
+
+  result_type min() const;
+
+* [*Returns:] The least value of the distribution.
+
+
+  result_type max() const;
+
+* [*Returns:] The greatest value of the distribution.
+
+  
+  void reset();
+
+* [*Effects:] Resets the state of the distribution function.
+
+
+  template<class UniformRandomNumberGenerator>
+  result_type operator()(UniformRandomNumberGenerator& urng);
+
+* [*Returns:] A uniform random number `x` in the range `min <= x <= max`.
+  
+
+[endsect][/uniform_mp_int_bits reference]
Added: sandbox/mp_math/libs/mp_math/doc/uniform_mp_int_reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/doc/uniform_mp_int_reference.qbk	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,61 @@
+[/ Copyright Kevin Sopp 2008.
+ / Distributed under the Boost Software License, Version 1.0.
+ / (See accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)]
+
+[section uniform_mp_int reference]
+
+[heading Synopsis]
+
+  // <boost/mp_math/mp_int.hpp>
+  template<class MpInt = mp_int<> >
+  struct uniform_mp_int
+  {
+    typedef MpInt input_type;
+    typedef MpInt result_type;
+
+    static const bool has_fixed_range = false;
+
+    uniform_mp_int(const MpInt& min, const MpInt& max);
+
+    result_type min() const;
+    result_type max() const;
+
+    void reset();
+    
+    template<class UniformRandomNumberGenerator>
+    result_type operator()(UniformRandomNumberGenerator& urng);
+  };
+
+
+[h3 Members]
+
+  uniform_mp_int(const MpInt& min, const MpInt& max);
+
+* [*Requires: ] `min <= max`
+* [*Effects:] Constructs a `uniform_mp_int` object. `min` and `max` are the
+parameters of the distribution.
+
+
+  result_type min() const;
+
+* [*Returns:] The `min` parameter of the distribution.
+
+
+  result_type max() const;
+
+* [*Returns:] The `max` parameter of the distribution.
+
+  
+  void reset();
+
+* [*Effects:] Resets the state of the distribution function.
+
+
+  template<class UniformRandomNumberGenerator>
+  result_type operator()(UniformRandomNumberGenerator& urng);
+
+* [*Returns:] A uniform random number `x` in the range `min <= x <= max`.
+  
+
+[endsect][/uniform_mp_int reference]
Added: sandbox/mp_math/libs/mp_math/index.html
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/index.html	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+  <title>Boost.Mp_math Documentation</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
+  <meta http-equiv="refresh" content="0; URL=doc/index.html" />
+</head>
+
+<body>
+  Automatic redirection failed, please go to <a href=
+  "doc/html/index.html">doc/html/index.html</a>
+</body>
+</html>
+
Added: sandbox/mp_math/libs/mp_math/test/add.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/add.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,217 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_positive_numbers1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("123456");
+  mp_int_type y("987777");
+  mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "1111233");
+  x = 999U;
+  y = 123456U;
+  z = x + y;
+  BOOST_CHECK_EQUAL(z, "124455");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_positive_numbers2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("21474836470");
+  const mp_int_type y("1234567845600");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "1256042682070");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_positive_numbers3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0xffffffffffffffff");
+  const mp_int_type y("0xffffffffffffffff");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "0x1fffffffffffffffe");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_positive_numbers4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0xffffffffffffffff");
+  const mp_int_type y("0xffffffff");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "0x100000000fffffffe");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_negative_numbers, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123456");
+  const mp_int_type y("-987777");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "-1111233");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_mixed_numbers1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123456");
+  const mp_int_type y("987777");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "864321");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_mixed_numbers2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("123456");
+  const mp_int_type y("-987777");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "-864321");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_mixed_numbers3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123456");
+  const mp_int_type y("123456");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_mixed_numbers4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("123456");
+  const mp_int_type y("-123456");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_mixed_numbers5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1000");
+  const mp_int_type y("-12345678901000");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "-12345678900000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_mixed_numbers6, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-12345678901000");
+  const mp_int_type y("1000");
+  const mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "-12345678900000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_large_and_small, mp_int_type, mp_int_types)
+{
+  mp_int_type x("123456789");
+  mp_int_type y("123");
+  mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "123456912");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_small_and_large, mp_int_type, mp_int_types)
+{
+  mp_int_type x("123");
+  mp_int_type y("123456789");
+  mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z, "123456912");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_large_and_large, mp_int_type, mp_int_types)
+{
+  mp_int_type x(
+    "76563204409879018101322737668344063995824904757312285775560614771886933079"
+    "77822556905976720912850551355328340715074887289899094852653102687850101285"
+    "85715275531977696497398396067715769512450915961775500023723324150851793075"
+    "51871751151095323159497918186624088118225730504044262785072662119470825604"
+    "40835072257208973943520251201155002832786969323087571220195329601804141972"
+    "71293425859967733061169954398382700046379970842289727254846347411792122453"
+    "98890529530611217475343335863666953662801553948341581412563112340543629531"
+    "01094529771464590172847457807673685591148055046712881378811934516545088775"
+    "38198087116656466935095055228728162461388333618793883566996616940381738437"
+    "03453867953392241443573580380271627517797446062394044787118140775664622031"
+    "49144609407766890328547643707523663509662747376486271392344480900673178645"
+    "33198519112197059826509662943577383543858946941049753393431035706592040680"
+    "43848484065292542884106550381079282660840705126574766636237650938379223350"
+    "073087806800887586256085275775217219429527000017403144");
+  
+  mp_int_type y(
+    "29156720459736055974643337783563754269574952607968485689453462316428566668"
+    "95504701770860331979649536167161534866285341319360225416010322271645564229"
+    "97610536562445338176729838019564690253931232562709745122032537539983616770"
+    "01864876491464203683664927984801289460556480278145114367860332493722569194"
+    "34026051618152579992400234314328079213866348120156368725488604236521299603"
+    "05243915357553896356662519397274629471920043679673543282319268893065423613"
+    "03777840501083119668898860689222271939900089123195611475211708096094521743"
+    "23436842195705603262202927396682954198215622617086455718070601797199587530"
+    "86110222151397352239086193648500251298495752840008363650931395221675337916"
+    "21665907282124706187656074325458499695895652068822763794228458103499408841"
+    "68233732651102406546734395563663969020820490032431359396293047454261598159"
+    "68165818673838448637209074584819780088546111644065538550490486693301185614"
+    "61602638472505490238203390055056474763248195271964604045005807592301719483"
+    "66411676459481184297663915491569500245585996483678005964410842919747216111"
+    "69086269285356198998091850661544255466466926579668887000118948737207396398"
+    "39189399212362197497646493143022100680619252808094160907526003969639965485"
+    "31238493375062268758735445211914107215235958346264702774326161208396163240"
+    "36339482493382189215697343908873498104516190541170342091008828518924813674"
+    "46253090923280613514725437269574928515018666111820866090440006060807129643"
+    "38626199608899966829344884873038261232122027815715568990196536130996880104"
+    "97887027262726591236620461428328000537452828616386217063092509908555188454"
+    "27278763741671312528892659532960085933913140197210561287118971031419725940"
+    "702202830556069344716729071140147820999566475298895832");
+  mp_int_type z = x + y;
+  BOOST_CHECK_EQUAL(z,
+    "29156720459736055974643337783563754269574952607968485689453462316428566668"
+    "95504701770860331979649536167161534866285341319360225416010322271645564229"
+    "97610536562445338176729838019564690253931232562709745122032537539983616770"
+    "01864876491464203683664927984801289460556480278145114367860332493722569194"
+    "34026051618152579992400234314328079213866348120156368725488604236521299603"
+    "05243915357553896356662519397274629471920043679673543282319268893065423613"
+    "03777840501083119668898860689222271939900089123195611475211708096094521743"
+    "23436842195705603262202927396682954198215622617086455718070601797199587530"
+    "86110222151397352239086193648500251298495752840008363650931395221675337916"
+    "98229111692003724288978811993802563691720556826135049569789072875386341921"
+    "46056289557079127459584946918992309735895377322330454248946150142111699445"
+    "53881094205816145134607470652535549600997027605841038574213810844152978690"
+    "13474389623600813397701308241680562881473925776008866830078469711772545088"
+    "07246748716690158241184166692724503078372965806765577184606172521551358084"
+    "40379695145323932059261805059926955512846897421958614254965296148999518852"
+    "38079928742973414972989829006689054343420806756435742320089116310183595016"
+    "32333023146526858931582903019587792806384013392977584153138095724941252015"
+    "74537569610038656150792399137601660565904524159964225658005445459306552111"
+    "49706958876672854958299017649846556032816112174214910877558146836471751674"
+    "87770809016666857157892528580561924741784775192201840382541017031670058750"
+    "31085546374923651063130124371905384081311775557435970456523545615147229134"
+    "71127247806963855412999209914039368594753845323785327923356621969798949290"
+    "775290637356956930972814346915365040429093475316298976");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(increment1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("0");
+  for (int i = 0; i < 10; ++i)
+    ++x;
+  BOOST_CHECK_EQUAL(x, "10");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(increment2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("-4");
+  for (int i = 0; i < 10; ++i)
+    ++x;
+  BOOST_CHECK_EQUAL(x, "6");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(increment3, mp_int_type, mp_int_types)
+{
+  mp_int_type x("-130");
+  for (int i = 0; i < 10; ++i)
+    ++x;
+  BOOST_CHECK_EQUAL(x, "-120");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(increment4, mp_int_type, mp_int_types)
+{
+  mp_int_type x("120");
+  for (int i = 0; i < 10; ++i)
+    ++x;
+  BOOST_CHECK_EQUAL(x, "130");
+}
+
Added: sandbox/mp_math/libs/mp_math/test/bitwise_ops.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/bitwise_ops.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,56 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(and_op1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x00ff0000000f");
+  const mp_int_type y("0xffffffffffff");
+  const mp_int_type z = x & y;
+  BOOST_CHECK_EQUAL(z, x);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(and_op2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x00ff0000000ffffffffff");
+  const mp_int_type y(         "0xffffffffffff");
+  const mp_int_type z = x & y;
+  BOOST_CHECK_EQUAL(z, "0xffffffffff");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(or_op1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x00ff0000000f");
+  const mp_int_type y("0xffffffffffff");
+  const mp_int_type z = x | y;
+  BOOST_CHECK_EQUAL(z, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(or_op2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x00ff0000000ffffffffff");
+  const mp_int_type y(         "0xaaffffffffff");
+  const mp_int_type z = x | y;
+  BOOST_CHECK_EQUAL(z, "0x00ff00000aaffffffffff");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(xor_op1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x00ff0000000f");
+  const mp_int_type y("0xffffffffffff");
+  const mp_int_type z = x ^ y;
+  BOOST_CHECK_EQUAL(z, "0xff00fffffff0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(xor_op2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x00ff0000000ffffffffff");
+  const mp_int_type y(         "0x33aaffffffff");
+  const mp_int_type z = x ^ y;
+  BOOST_CHECK_EQUAL(z,"0x00ff00000335500000000");
+}
+
Added: sandbox/mp_math/libs/mp_math/test/bool_conversion.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/bool_conversion.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,40 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(bool1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1");
+  const mp_int_type y("0");
+  BOOST_CHECK_EQUAL(x, true);
+  BOOST_CHECK_EQUAL(y, false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(bool_or, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1");
+  const mp_int_type y("0");
+  const bool z = x || y;
+  BOOST_CHECK_EQUAL(z, true);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(bool_and1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1");
+  const mp_int_type y("0");
+  const bool z = x && y;
+  BOOST_CHECK_EQUAL(z, false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(bool_and2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1");
+  const mp_int_type y("1");
+  const bool z = x && y;
+  BOOST_CHECK_EQUAL(z, true);
+}
+
Added: sandbox/mp_math/libs/mp_math/test/cmp.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/cmp.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,152 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_eq1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-1");
+  const mp_int_type y("-1");
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("12");
+  const mp_int_type y("13");
+  BOOST_CHECK_LT(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1");
+  const mp_int_type y("123456789");
+  BOOST_CHECK_LT(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-1");
+  const mp_int_type y("0");
+  BOOST_CHECK_LT(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123");
+  const mp_int_type y("-10");
+  BOOST_CHECK_LT(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123456789");
+  const mp_int_type y("123456798");
+  BOOST_CHECK_LT(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_le1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const mp_int_type y("0");
+  BOOST_CHECK_LE(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_le2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-1");
+  const mp_int_type y("0");
+  BOOST_CHECK_LE(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_le3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123456789");
+  const mp_int_type y("-123456789");
+  BOOST_CHECK_LE(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_le4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("11");
+  const mp_int_type y("49941");
+  BOOST_CHECK_LE(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_eq_to_integral_type1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  BOOST_CHECK_EQUAL(x, 0);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_eq_to_integral_type2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("20");
+  BOOST_CHECK_EQUAL(x, 20U);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_eq_to_integral_type3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("300");
+  BOOST_CHECK_EQUAL(x, 300);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_eq_to_integral_type4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-1");
+  BOOST_CHECK_EQUAL(x, -1);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_eq_to_integral_type5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-32101");
+  BOOST_CHECK_EQUAL(x, -32101);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_lt_integral_type, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("123456789");
+  BOOST_CHECK_LT(x, 123456790);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_lt_unsigned_integral_type, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("123456789");
+  BOOST_CHECK_LT(x, 123456790U);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_le_integral_type1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  BOOST_CHECK_LE(x, 123456789);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_le_integral_type2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("32101");
+  BOOST_CHECK_LE(x, 32102);
+}
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_le_unsigned_integral_type, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  BOOST_CHECK_LE(x, 32101U);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_integral_type_lt_mp_int, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("32101");
+  BOOST_CHECK_LT(32100, x);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_integral_type_le_mp_int, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("32101");
+  BOOST_CHECK_LE(x, 32102);
+}
+
+
Added: sandbox/mp_math/libs/mp_math/test/compile_all.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/compile_all.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,96 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Compile all functions in the presence of the cmath header
+
+#include <cmath>
+#include <boost/mp_math/mp_int.hpp>
+
+
+// first explicitly instantiate the class template
+template class boost::mp_math::mp_int<>;
+
+
+
+// a different allocator type used in conjunction with the basic_string class
+// template
+template<typename T>
+struct my_alloc : std::allocator<T>
+{
+  template<typename U> struct rebind { typedef my_alloc<U> other; };
+};
+
+typedef std::basic_string<
+  char, std::char_traits<char>, my_alloc<char> > my_string;
+
+
+
+template<class MpInt>
+MpInt compile_constructors()
+{
+  const std::string  a("0x123456789abcdefABCDEF");
+  const std::wstring b(L"012345676543210");
+  const my_string    c("0xabcdefabcdef0001");
+
+  // constructors from string
+  MpInt u("0x123456789abcdef");
+  MpInt v(L"0x123456789abcdef");
+  MpInt w(a);
+  MpInt x(a.begin(), a.end());
+  MpInt y(b);
+  MpInt z(c);
+
+  const signed char sc = -100;
+  const unsigned char uc = 200;
+  const int i = -12000;
+  const unsigned int ui = 22000;
+
+  // constructors from integral type
+  MpInt m(sc);
+  MpInt n(uc);
+  MpInt o(i);
+  MpInt p(ui);
+
+  // copy constructor
+  MpInt copy(z);
+
+  return u + v + w + x + y + z + copy + m + n + o + p;
+}
+
+template<class MpInt>
+MpInt compile_assignment_ops()
+{
+  MpInt a = "0xfffffffffffffffffff";
+  MpInt b = "0xabcd";
+  MpInt c = 1000;
+  MpInt d = "07777777777777777777000001";
+
+  a = b;
+  b = d;
+
+  const my_string s("0xa123b566c78e9aafdf");
+  c = s;
+
+  d.assign("-12345678901234", std::ios_base::dec);
+
+  return a + b + c + d;
+}
+
+
+int main(int, char**)
+{
+  
+  typedef boost::mp_math::mp_int<> mp_int_type;
+  
+  mp_int_type a("0");
+
+  a += compile_constructors<mp_int_type>();
+  a += compile_assignment_ops<mp_int_type>();
+  a = boost::mp_math::pow(a, 3);
+  a = boost::mp_math::abs(a);
+
+  return 0;
+}
+
Added: sandbox/mp_math/libs/mp_math/test/ctors.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/ctors.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,188 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor, mp_int_type, mp_int_types)
+{
+  const mp_int_type a;
+  BOOST_CHECK_EQUAL(a.size(), 0U);
+  BOOST_CHECK_EQUAL(a.is_positive(), true);
+  BOOST_CHECK_EQUAL(a.is_negative(), false);
+  BOOST_CHECK_EQUAL(a, "");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_decimal_string1, mp_int_type, mp_int_types)
+{
+  const mp_int_type y("12");
+  BOOST_CHECK_EQUAL(y, "12");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_decimal_string2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("123456789");
+  BOOST_CHECK_EQUAL(x, "123456789");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_decimal_string3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1000000000");
+  BOOST_CHECK_EQUAL(x, "1000000000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_decimal_string4, mp_int_type, mp_int_types)
+{
+  const mp_int_type y("0");
+  BOOST_CHECK_EQUAL(y.is_zero(), true);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_positive_decimal_string1, mp_int_type, mp_int_types)
+{
+  const mp_int_type z("+1");
+  BOOST_CHECK_EQUAL(z, "1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_negative_decimal_string1, mp_int_type, mp_int_types)
+{
+  const mp_int_type z("-1");
+  BOOST_CHECK_EQUAL(z, "-1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_negative_decimal_string2, mp_int_type, mp_int_types)
+{
+  const mp_int_type z("-888888");
+  BOOST_CHECK_EQUAL(z, "-888888");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_octal_string1, mp_int_type, mp_int_types)
+{
+  const mp_int_type y("012");
+  BOOST_CHECK_EQUAL(y, "10");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_octal_string2, mp_int_type, mp_int_types)
+{
+  const mp_int_type y("000000000000000000000000000000000");
+  BOOST_CHECK_EQUAL(y.is_zero(), true);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_octal_string3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0123456777");
+  BOOST_CHECK_EQUAL(x, "21913087");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_octal_string4, mp_int_type, mp_int_types)
+{
+  const mp_int_type z("-0777777");
+  BOOST_CHECK_EQUAL(z, "-262143");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_hexadecimal_string1, mp_int_type, mp_int_types)
+{
+  const mp_int_type y("0xF");
+  BOOST_CHECK_EQUAL(y, "15");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_hexadecimal_string2, mp_int_type, mp_int_types)
+{
+  const mp_int_type y("0xa0");
+  BOOST_CHECK_EQUAL(y, "160");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_hexadecimal_string3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x123456789abcdef");
+  BOOST_CHECK_EQUAL(x, "0x123456789abcdef");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_hexadecimal_string4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-0x8F888b");
+  BOOST_CHECK_EQUAL(x, "-0x8F888b");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_hexadecimal_string5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0xA0000000");
+  BOOST_CHECK_EQUAL(x, "2684354560");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_long_string, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("87500402519005030061267904448809305029512439942506161234260852587645856336946409871074842737283625535525153833045575858681216");
+  BOOST_CHECK_EQUAL(x, "87500402519005030061267904448809305029512439942506161234260852587645856336946409871074842737283625535525153833045575858681216");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_iterators1, mp_int_type, mp_int_types)
+{
+  const std::string s("123456789");
+  const mp_int_type z(s.begin(), s.end());
+  BOOST_CHECK_EQUAL(z, "123456789");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_unsigned_integral_type1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x(9999999U);
+  BOOST_CHECK_EQUAL(x, "9999999");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_unsigned_integral_type2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x(123456U);
+  BOOST_CHECK_EQUAL(x, "123456");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_integral_type_signed_char, mp_int_type, mp_int_types)
+{
+  signed char c = -14;
+  const mp_int_type x(c);
+  BOOST_CHECK_EQUAL(x, "-14");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_integral_type_unsigned_char, mp_int_type, mp_int_types)
+{
+  unsigned char c = 42;
+  const mp_int_type x(c);
+  BOOST_CHECK_EQUAL(x, "42");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_integral_type_short_int, mp_int_type, mp_int_types)
+{
+  short int c = -14789;
+  const mp_int_type x(c);
+  BOOST_CHECK_EQUAL(x, "-14789");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_integral_type_int, mp_int_type, mp_int_types)
+{
+  int c = -9999;
+  const mp_int_type x(c);
+  BOOST_CHECK_EQUAL(x, "-9999");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_integral_type_long_int, mp_int_type, mp_int_types)
+{
+  const long int c = -100000000;
+  const mp_int_type x(c);
+  BOOST_CHECK_EQUAL(x, "-100000000");
+}
+
+#ifndef BOOST_NO_CWCHAR
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_wchar_t, mp_int_type, mp_int_types)
+{
+  const mp_int_type x(L"0xA0000000");
+  BOOST_CHECK_EQUAL(x, "2684354560");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_from_wstring, mp_int_type, mp_int_types)
+{
+  const std::wstring s(L"0xA0000000");
+  const mp_int_type x(s);
+  BOOST_CHECK_EQUAL(x, "2684354560");
+}
+#endif
Added: sandbox/mp_math/libs/mp_math/test/div.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/div.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,96 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type y("123456");
+  const mp_int_type z = x / y;
+  BOOST_CHECK_EQUAL(z, "8");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type y("-123456");
+  const mp_int_type z = x / y;
+  BOOST_CHECK_EQUAL(z, "-8");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("263825472");
+  const mp_int_type y("123456");
+  const mp_int_type z = x / y;
+  BOOST_CHECK_EQUAL(z, "2137");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide_by_2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("263825472");
+  x.divide_by_2();
+  BOOST_CHECK_EQUAL(x, "131912736");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(shift_right1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("263825472");
+  x >>= 3;
+  BOOST_CHECK_EQUAL(x, "32978184");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mod1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type y("123456");
+  const mp_int_type z = x % y;
+  BOOST_CHECK_EQUAL(z, "129");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mod2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-987777");
+  const mp_int_type y("123456");
+  const mp_int_type z = x % y;
+  BOOST_CHECK_EQUAL(z, "-129");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mod3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type y("-123456");
+  const mp_int_type z = x % y;
+  BOOST_CHECK_EQUAL(z, "129");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mod4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-987777");
+  const mp_int_type y("-123456");
+  const mp_int_type z = x % y;
+  BOOST_CHECK_EQUAL(z, "-129");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mod5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123456");
+  const mp_int_type y("123456");
+  const mp_int_type z = x % y;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mod6, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const mp_int_type y("5");
+  const mp_int_type z = x % y;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+
+
Added: sandbox/mp_math/libs/mp_math/test/gcd.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/gcd.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,32 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(gcd1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("10");
+  const mp_int_type y("2");
+  const mp_int_type z = boost::mp_math::gcd(x,y);
+  BOOST_CHECK_EQUAL(z, "2");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(gcd2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("456489798");
+  const mp_int_type y("987");
+  const mp_int_type z = boost::mp_math::gcd(x,y);
+  BOOST_CHECK_EQUAL(z, "3");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(gcd3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-16384");
+  const mp_int_type y("16384");
+  const mp_int_type z = boost::mp_math::gcd(x,y);
+  BOOST_CHECK_EQUAL(z, "16384");
+}
Added: sandbox/mp_math/libs/mp_math/test/integral_ops.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/integral_ops.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,257 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_signed_char_min, mp_int_type, mp_int_types)
+{
+  const signed char x = std::numeric_limits<signed char>::min();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_signed_char_max, mp_int_type, mp_int_types)
+{
+  const signed char x = std::numeric_limits<signed char>::max();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_unsigned_char_min, mp_int_type, mp_int_types)
+{
+  const unsigned char x = std::numeric_limits<unsigned char>::min();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_unsigned_char_max, mp_int_type, mp_int_types)
+{
+  const unsigned char x = std::numeric_limits<unsigned char>::max();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_int_min, mp_int_type, mp_int_types)
+{
+  const int x = std::numeric_limits<int>::min();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_int_max, mp_int_type, mp_int_types)
+{
+  const int x = std::numeric_limits<int>::max();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_unsigned_int_min, mp_int_type, mp_int_types)
+{
+  const unsigned int x = std::numeric_limits<unsigned int>::min();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(equal_unsigned_int_max, mp_int_type, mp_int_types)
+{
+  const unsigned int x = std::numeric_limits<unsigned int>::max();
+  const mp_int_type y(x);
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_signed_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type z = x + 1;
+  BOOST_CHECK_EQUAL(z, "987778");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_signed_integral2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type z = x + (-1);
+  BOOST_CHECK_EQUAL(z, "987776");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_unsigned_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("9999999");
+  const mp_int_type z = x + 1U;
+  BOOST_CHECK_EQUAL(z, "10000000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_signed_char_min, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const mp_int_type z = x + std::numeric_limits<signed char>::min();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<signed char>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_signed_char_max, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const mp_int_type z = x + std::numeric_limits<signed char>::max();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<signed char>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_int_min, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const mp_int_type z = x + std::numeric_limits<int>::min();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<int>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(add_int_max, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const mp_int_type z = x + std::numeric_limits<int>::max();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<int>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(subtract_signed_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type z = x - 12345;
+  BOOST_CHECK_EQUAL(z, "975432");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(subtract_signed_integral2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("98000");
+  const mp_int_type z = x - (-1);
+  BOOST_CHECK_EQUAL(z, "98001");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(subtract_signed_integral3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("125642682070");
+  const long y = 2147483647;
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "123495198423");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(subtract_unsigned_char1, mp_int_type, mp_int_types)
+{
+  const unsigned char y = 14;
+  const mp_int_type x("987777");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "987763");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(multiply_by_signed_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type z = x * 12345;
+  BOOST_CHECK_EQUAL(z, "12194107065");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(multiply_by_signed_integral2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type z = x * -12345;
+  BOOST_CHECK_EQUAL(z, "-12194107065");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(multiply_by_signed_integral3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-987777");
+  const mp_int_type z = x * -12345;
+  BOOST_CHECK_EQUAL(z, "12194107065");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(multiply_by_unsigned_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1256");
+  const mp_int_type z = x * 100U;
+  mp_int_type w("125600");
+  BOOST_CHECK_EQUAL(z, "125600");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(multiply_by_zero1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-9877234234252377");
+  const mp_int_type z = x * 0;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(multiply_by_negative_zero1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-9877234234252377");
+  const mp_int_type z = x * -0;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(divide_by_signed_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("786432");
+  const mp_int_type z = x / 12;
+  BOOST_CHECK_EQUAL(z, "65536");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modulo_signed_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("786432");
+  const mp_int_type z = x % 12;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modulo_signed_integral2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-987777");
+  const mp_int_type z = x % 123456;
+  BOOST_CHECK_EQUAL(z, "-129");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modulo_signed_integral3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987777");
+  const mp_int_type z = x % -123456;
+  BOOST_CHECK_EQUAL(z, "129");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modulo_signed_integral4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-987777");
+  const mp_int_type z = x % -123456;
+  BOOST_CHECK_EQUAL(z, "-129");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modulo_unsigned_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987771");
+  const mp_int_type z = x % 16U;
+  BOOST_CHECK_EQUAL(z, "11");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modulo_unsigned_integral2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-987771");
+  const mp_int_type z = x % 16U;
+  BOOST_CHECK_EQUAL(z, "-11");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(bitwise_or_signed_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("786432");
+  const mp_int_type z = x | 1;
+  BOOST_CHECK_EQUAL(z, "786433");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(bitwise_or_signed_integral2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("786432");
+  const mp_int_type z = x | -1;
+  BOOST_CHECK_EQUAL(z, "786433");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(bitwise_or_unsigned_integral1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("786432");
+  const mp_int_type z = x | 1U;
+  BOOST_CHECK_EQUAL(z, "786433");
+}
+
Added: sandbox/mp_math/libs/mp_math/test/jacobi.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/jacobi.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,32 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1236");
+  const mp_int_type y("20003");
+  const int z = boost::mp_math::jacobi(x,y);
+  BOOST_CHECK_EQUAL(z, 1);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("987897");
+  const mp_int_type y("987");
+  const int z = boost::mp_math::jacobi(x,y);
+  BOOST_CHECK_EQUAL(z, 0);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("610");
+  const mp_int_type y("987");
+  const int z = boost::mp_math::jacobi(x,y);
+  BOOST_CHECK_EQUAL(z, -1);
+}
Added: sandbox/mp_math/libs/mp_math/test/jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/jamfile.v2	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,44 @@
+# Copyright Kevin Sopp 2008.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+alias boost_test
+: $(BOOST_ROOT)/libs/test/build//boost_unit_test_framework/<link>shared ;
+
+alias boost_serialization
+:  $(BOOST_ROOT)/libs/serialization/build//boost_serialization/<link>shared ;
+
+project
+    : requirements
+      <include>../../..
+      <link>static
+      <define>BOOST_TEST_DYN_LINK
+      <define>BOOST_TEST_MAIN
+      #<define>BOOST_MP_MATH_MP_INT_USE_ASM
+    ;
+
+unit-test add             : add.cpp             boost_test ;
+unit-test bitwise_ops     : bitwise_ops.cpp     boost_test ;
+unit-test bool_conversion : bool_conversion.cpp boost_test ;
+unit-test cmp             : cmp.cpp             boost_test ;
+unit-test ctors           : ctors.cpp           boost_test ;
+unit-test div             : div.cpp             boost_test ;
+unit-test gcd             : gcd.cpp             boost_test ;
+unit-test integral_ops    : integral_ops.cpp    boost_test ;
+unit-test jacobi          : jacobi.cpp          boost_test ;
+unit-test mul             : mul.cpp             boost_test ;
+unit-test pow             : pow.cpp             boost_test ;
+unit-test prime           : prime.cpp           boost_test ;
+unit-test random          : random.cpp          boost_test ;
+unit-test root            : root.cpp            boost_test ;
+unit-test serialization   : serialization.cpp   boost_test boost_serialization ;
+unit-test shift           : shift.cpp           boost_test ;
+unit-test sqr             : sqr.cpp             boost_test ;
+unit-test sub             : sub.cpp             boost_test ;
+unit-test stream_io       : stream_io.cpp       boost_test ;
+unit-test string_ops      : string_ops.cpp      boost_test ;
+unit-test to_integral     : to_integral.cpp     boost_test ;
+unit-test traits          : traits.cpp          boost_test ;
+#unit-test compile_all     : compile_all.cpp     boost_test ;
+
Added: sandbox/mp_math/libs/mp_math/test/mul.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/mul.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,368 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mul1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("12");
+  const mp_int_type y("22459455");
+  const mp_int_type z = x * y;
+  BOOST_CHECK_EQUAL(z, "269513460");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mul2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("280708");
+  const mp_int_type y("2245945");
+  const mp_int_type z = x * y;
+  BOOST_CHECK_EQUAL(z, "630454729060");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mul3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("65536");
+  const mp_int_type y("65536");
+  const mp_int_type z = x * y;
+  BOOST_CHECK_EQUAL(z, "4294967296");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mul4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1234567890123456789");
+  const mp_int_type y("9877771234567890123");
+  const mp_int_type z = x * y;
+  BOOST_CHECK_EQUAL(z, "12194779192182653090000267987090395047");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mul5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("789456120556882111687894651457623561325656871513");
+  const mp_int_type y("54564563128978513215");
+  const mp_int_type z = x * y;
+  BOOST_CHECK_EQUAL(z, "43076328327684465744675616648356768900793087398990591539995027544295");
+}
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mul6, mp_int_type, mp_int_types)
+{
+  // this tests karatsuba multiplication for 8, 16 and 32 bit digit_type
+  const mp_int_type x(
+    "87500402519005030061267904448809305029512439942506161234260852587645856336"
+    "94640987107484273728362553552515383304557585868121651546490330517814007487"
+    "34682745159208158750835203309620570274592666481348052963762094268695162425"
+    "18850320172906096781969070339129822281355221058882087466637338881223511228"
+    "63144016884857141834687376804878770495858121023810198067988560350169566260"
+    "59441070673981642057711662497893572913873133654626566743289483229067287310"
+    "16863866837882738076436342057320810154710294295605465397209378421688020320"
+    "35702406032061642794728883255642074744145228324022219347019013411158803532"
+    "45994041206565648683544493690427219798945006072652042753387791345064784511"
+    "50227920502852884378111055250850357557404795594025600468996407045934090727"
+    "08041078777870387730504");
+  const mp_int_type y(
+    "87500402519005030061267904448809305029512439942506161234260852587645856336"
+    "94640987107484273728362553552515383304557585868121651546490330517814007487"
+    "34682745159208158750835203309620570274592666481348052963762094268695162425"
+    "18850320172906096781969070339129822281355221058882087466637338881223511228"
+    "63144016884857141834687376804878770495858121023810198067988560350169566260"
+    "59441070673981642057711662497893572913873133654626566743289483229067287310"
+    "16863866837882738076436342057320810154710294295605465397209378421688020320"
+    "35702406032061642794728883255642074744145228324022219347019013411158803532"
+    "45994041206565648683544493690427219798945006072652042753387791345064784511"
+    "50227920502852884378111055250850357557404795594025600468996407045934090727"
+    "08041078777870387730504938308922524767076619493071600607096868205642593777"
+    "83064672064693123083586511497969514956199763260628691421422356349215807298"
+    "53893432372651287096347803705731068491268031212879821570628466049198139563"
+    "07225373203247341492567070512742515269237115281940442618925655326204507165"
+    "43018685973456180521304052296263372550548657267007681462726186588489921154"
+    "03738735312309811855295260282588410141887442245474311543699839300870263148"
+    "89969642893224272388306131900850182843780525186002406202200057400419364041"
+    "12480917884571681605871307558328122948240801747503773233227317344565943160"
+    "78184811118761000119446172201197213166958413376441353073591860771242469526"
+    "34162171790217465073689788174652534961638870987430329380376975097234424950"
+    "28626203467171261194438985008578074151902043501430333019202385199270557942"
+    "82069487032265791643884311563532673152911052140807076806223793474752085674"
+    "51690168224265201474031350018449280412602665727006489664736651532321662145"
+    "22395731894311806382965185156526606660906262290677223798531105431808835740"
+    "80068277468617762211054331907328141344243411630209274782352265433366236954"
+    "62340796945506470082986574244652633468578747126384423018749343237426427830"
+    "62597495610006322516869046617226177792891514414040880511098169575819779926"
+    "53267511946096311413217967853431922008343789549408902117132966444741997352"
+    "58418657379544687590177580275674377304583931111620683151992749560156615440"
+    "09956001573216294273550652829235006290995819615078227235050765818475452342"
+    "95118077784320900839083926375344280915278665450149678774001364483022411118"
+    "86989210613864536835695555040115554865868694788922281253334356037168116291"
+    "99227045413249316876243936449829162763370534672670641521910718921661373160"
+    "93948899172794003245737017747952580428164207428777214495975431645589773283"
+    "12391742034637254884903040666536846003583703264118132242307521988982264762"
+    "13953490712153270721924306359669195669881431604926261623147833800912453474"
+    "06542388952383807976431616628717886593805647129190060659586374949333503420"
+    "5241703455510726935");
+  
+  const mp_int_type z = x * y;
+  
+  const mp_int_type w(
+    "76563204409879018101322737668344063995824904757312285775560614771886933079"
+    "77822556905976720912850551355328340715074887289899094852653102687850101285"
+    "85715275531977696497398396067715769512450915961775500023723324150851793075"
+    "51871751151095323159497918186624088118225730504044262785072662119470825604"
+    "40835072257208973943520251201155002832786969323087571220195329601804141972"
+    "71293425859967733061169954398382700046379970842289727254846347411792122453"
+    "98890529530611217475343335863666953662801553948341581412563112340543629531"
+    "01094529771464590172847457807673685591148055046712881378811934516545088775"
+    "38198087116656466935095055228728162461388333618793883566996616940381738437"
+    "03453867953392241443573580380271627517797446062394044787118140775664622031"
+    "49144609407766890328547643707523663509662747376486271392344480900673178645"
+    "33198519112197059826509662943577383543858946941049753393431035706592040680"
+    "43848484065292542884106550381079282660840705126574766636237650938379223350"
+    "07308780680088758625608527577521721942952700001740314426688555136034651920"
+    "92948869415921251533176579828351648585255631612516166131530519177426817087"
+    "53127165191235539369253485175856164884318259457319518574027800748530624722"
+    "30999853784133144744590149844870058500033133557974954747400058296439058233"
+    "59080109028703731380219724583279605028258137468666258706566102379192203551"
+    "90274426910716106736469216457355540125186992654301008720830993368763363204"
+    "11036960264301276622450044075944548104639523605502445335712149154791061273"
+    "09156720459736055974643337783563754269574952607968485689453462316428566668"
+    "95504701770860331979649536167161534866285341319360225416010322271645564229"
+    "97610536562445338176729838019564690253931232562709745122032537539983616770"
+    "01864876491464203683664927984801289460556480278145114367860332493722569194"
+    "34026051618152579992400234314328079213866348120156368725488604236521299603"
+    "05243915357553896356662519397274629471920043679673543282319268893065423613"
+    "03777840501083119668898860689222271939900089123195611475211708096094521743"
+    "23436842195705603262202927396682954198215622617086455718070601797199587530"
+    "86110222151397352239086193648500251298495752840008363650931395221675337916"
+    "21665907282124706187656074325458499695895652068822763794228458103499408841"
+    "68233732651102406546734395563663969020820490032431359396293047454261598159"
+    "68165818673838448637209074584819780088546111644065538550490486693301185614"
+    "61602638472505490238203390055056474763248195271964604045005807592301719483"
+    "66411676459481184297663915491569500245585996483678005964410842919747216111"
+    "69086269285356198998091850661544255466466926579668887000118948737207396398"
+    "39189399212362197497646493143022100680619252808094160907526003969639965485"
+    "31238493375062268758735445211914107215235958346264702774326161208396163240"
+    "36339482493382189215697343908873498104516190541170342091008828518924813674"
+    "46253090923280613514725437269574928515018666111820866090440006060807129643"
+    "38626199608899966829344884873038261232122027815715568990196536130996880104"
+    "97887027262726591236620461428328000537452828616386217063092509908555188454"
+    "27278763741671312528892659532960085933913140197210561287118971031419725940"
+    "70220283055606934471672907114014782099956647529889583250740029484462218658"
+    "62960901244568848989478467720707250809806379509214397878558772543587967635"
+    "96161034019645060913914198361071023036142203589230741296078930717247341831"
+    "26204308310630181474853421564903407641109879794777661716811159608177803322"
+    "61170286373919980640839261570604290919653466216587527613203517128403418424"
+    "791614399508711582164287714644181913925240");
+
+  BOOST_CHECK_EQUAL(z, w);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(mul7, mp_int_type, mp_int_types)
+{
+  // this tests toom cook multiplication for 8, 16 and 32 bit digit_type
+  const mp_int_type x(
+    "0x5004a2519b00503006126bb044af8930502951243994250616123426085258764a856336"
+    "35702406cff061642794728883255642074744145228324022219347019013411158803532"
+    "4599404120656564868354acc9369a42721979894500607265f042a53387791b3dd4784511"
+    "50227920502852884378111055ccff50357557404795594025600468996407045934090727"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "6ca63511429296727b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e927"
+    "22c85a2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa07019a4c"
+    "1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3748f82ee78a5636"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "9464098710748f27372836255355251ae330455ffaa58681216515eeff0330517814dd7487"
+    "34682745159208158750835203309620570274592666481348052963762094268695162425"
+    "18850320172906096781969070339129822281355221058882087466637338881223511228"
+    "63144016884857141834687376804878770495858121023810198067988560350169566260"
+    "5944107067ac5771a1662497b8b93cfe57291387313365462656674328aaaaaf9067287310"
+    "ea6863ec68378827380764363420573208101547102942bf05465397209378421688020320"
+    "35702406cff061642794728883255642074744145228324022219347019013411158803532"
+    "4599404120656564868354acc9369a42721979894500607265f042a53387791b3dd4784511"
+    "50227920502852884378111055ccff50357557404795594025600468996407045934090727"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "6ca63511429296727b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e927"
+    "22c85a2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa07019a4c"
+    "1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3748f82ee78a5636"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "18850320172906096781969070339129822281355221058882087466637338881223511228"
+    "63144016884857141834687376804878770495858121023810198067988560350169566260"
+    "59441070673981642057711662497893572913873133654626566743289483229067287310"
+    "35702406cff061642794728883255642074744145228324022219347019013411158803532"
+    "4599404120656564868354acc9369a42721979894500607265f042a53387791b3dd4784511"
+    "50227920502852884378111055ccff50357557404795594025600468996407045934090727"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "6ca63511429296727b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e927"
+    "22c85a2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa07019a4c"
+    "1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3748f82ee78a5636"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "16863866837882738076436342057320810154710294295605465397209378421688020320"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "f84c878148cc7020890befffaa4506cebbef9a3f7c67178f2");
+  const mp_int_type y(
+    "0x875aa402519005030061267904ccc8809d0502243994250616123426085258764585633a"
+    "94640987107484273728362553552515383304557585868121651546490330517814007487"
+    "34682745159208158750835203309620570274592666481348052963762094268695162425"
+    "18850320172906096781969070339129822281355221058882087466637338881223511228"
+    "63144016884857141834687376804878770495858121023810198067988560350169566260"
+    "59441070673981642057711662497893572913873133654626566743289483229067287310"
+    "16863866837882738076436342057320810154710294295605465397209378421688020320"
+    "357024060320616427947288832ff6420747dd145228324022219347019013411158803532"
+    "45994041206565648683544493690427219798945006072652042753387791345064784511"
+    "50227920502852884378111055250850357557404795594025600468996407045934090727"
+    "08041078777870387730504938308922524767076619493071600607096868205642593777"
+    "35702406cff061642794728883255642074744145228324022219347019013411158803532"
+    "4599404120656564868354acc9369a42721979894500607265f042a53387791b3dd4784511"
+    "50227920502852884378111055ccff50357557404795594025600468996407045934090727"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "6ca63511429296727b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e927"
+    "22c85a2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa07019a4c"
+    "1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3748f82ee78a5636"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "83064672064693123083586511497969514956199763260628691421422356349215807298"
+    "53893432372651287096347803705731068491268031212879821570628466049198139563"
+    "07225373203247341492562497b8b93568861230addd281940442618925655326204507165"
+    "43018685973456180521304052296263372550548657267007681462726186588489921154"
+    "03738735312309811855295260282588410141887442245474311543699839300870263148"
+    "cdd69642893224272388306131f0a850182843780525186002406202200057400419364041"
+    "12480917884571681605871307558328122948240801747503773233227317344565943160"
+    "78184811118761000119446172201197213166958413376441353073591860771242469526"
+    "34162171790217465073689788174652534961638870987430329380376975097234424950"
+    "286262034671712611944389850085780a4151902043501430333019202385199270557942"
+    "82069487032265791643884311563532673152911052140807076806223793474752085674"
+    "51690168224265201474031350018449280412602665727006489664736651532321662145"
+    "22395731894311806382965185156526606660906262290677223798531105431808835740"
+    "80068277468617762211054331907328141344243411630209274782352265433366236954"
+    "62340796945506470082986574244652633468578747126384423018749343237426427830"
+    "62597495610006322516869046617226177792891514414040880511098169575819779926"
+    "53267511946096311413217967853431922008343789549408902117132966444741997352"
+    "5841865737954468759a177580275674377304583931111620683151992749560156615440"
+    "09956001573216294273550652829235006290995819615078227235050765818475452342"
+    "95118077784320900839083926375344280915278665450149678774001364483022411118"
+    "86989210613864536835695555040115554865868694788922281253334356037168116291"
+    "99227045413249316876243936449829162763370534672670641521910718921661373160"
+    "93948899172794003245737017747952580428164207428777214495975431645589773283"
+    "12391742034637254884903040666536846003583703264118132242307521988982264762"
+    "13953490712153270721924306359669195669881431604926261623147833800912453474"
+    "06542388952383807976431616628717886593805647129190060659586374949333503420"
+    "ffab023789d7d78f78a45a45fee789001a1a");
+  
+  const mp_int_type z = x * y;
+
+  const mp_int_type w(
+    "0x2a4ec67dcaf1afdd14bf63d7cd883f269ca00be2cae5c539545352050e33af7bb008713c"
+    "63587bc02911b0cb1fb807d94cd4a937f6e19801a28500f45ba1dc90a548e8e15e0c31536b"
+    "39f3940191a76b6fd96fda83c7aa9aa675f536633917587fbdb4990f73dc4650e19af67392"
+    "712b0a94aeec78f21523bd2ae92cee0b5d42ce2ead649060ff8134dbca0790f051b132b8fd"
+    "2f0bbe66f3226f7fe7a80c0be18fcd0238ff0100e4353f4973c1cb72c40e83804192fbd008"
+    "1e3d4dfe03e1d4c8d1ed4ba8ffe7cf5d00237598de949ab89cd6f95cbc3545a4d797e425f9"
+    "041fbe52955af28221505ce3e53cb5bc12d8d9a13f39704463db4db21aaea4fc29643a2746"
+    "2e6d3b40f9eb621106bda6223bf2aaa4f027e037acb45406cd39b242c90df3b4fae1bf788a"
+    "1529dac1ce1b77f4d1557e2aa8a4adf9c6b3b0c364ce68300b5f65efc8166dae1b2e0f8443"
+    "76975b12b72c36f2dfc4a533adca3db43955265d91d15232bcfd712e46dd4cd4f63981317b"
+    "31be8e9fc0a56275da498e8a4c13419eb8560fa05d73373ff238787b77c0b45c0b44b6b042"
+    "365bfb3b3a4d96cdb3ad7cb9b9248498a02b43a16206db5cc3f52c4cdf2c58807a68a6d1b0"
+    "f24bf8daa4eaf6ffdd3e781fd52b5fe609678d045944d7ea6a6689954b82a737b136a86d32"
+    "e8de0c6b88e66300487b83deb53038fc298c2b1d1ffe64ab7ebf0e7682b285bb567c3ad4bc"
+    "69c0e0216f5c8df2681a3e84435b39dbd4a3cd5dcdf0b776bc0b5281f8806155318e70d237"
+    "4267ca699ebdc5df58e282f7a6d2a7401a3544193741e9597df7fb92c7a0c87128b53ae873"
+    "14aacf233fc20cba4ac4835579bd82b6efcadd591dbf826d470795d64bb698202e3fc5bbd3"
+    "9ca2249167520764d448a95c7a7ed00f43d2f36f4158fccacf2f5738878099da8a323e7d2c"
+    "57579da5e348b45aabe59366085532c73c2388b3a2672b08758bdaae3746364b49d0217b27"
+    "5d22b2b4916628afd5009e103803f4ba5241413200d85e119ceb4dc876c1521047a8be7650"
+    "767b0d83fcbf991c6b04a51213692867fe4c9e452b2800fe5fc57df9d8f75cab72609a49af"
+    "92b1e2407b64ea424344a626b2e86eacdf18af6a000af8c5607019df1d670307a65df3e4bf"
+    "51e9809212a3288001e1df69a6070558e24f686ff34b50e7b2daf5f3f7abc7be88fff8fb5d"
+    "f0aab1f952f91eec5c5ff7e25d2babb61db263e7381fbe40ad81b3494c323a35d3333fcadd"
+    "d6b057c88fe2f43ec1bf754de9fdbc768457d7fc44c90c2e44f79c32849f56d7d2152b96d1"
+    "4b7735e8eae29d8e9ccdd61be1f73f7d1d2e16732505448a33145a5b1d5c342f0990a0a731"
+    "a5e034cb3c0f5658e20b8ac7f4e93c249ec9badb93c4e064b59c34b11e4327d0dacb0951ac"
+    "1c13831520a06deee884613bce16fe5b92e1e0776caf6aa1a7aadccad11a741e7c08512816"
+    "e1c4a0f8910c35450a7448c180528decdc54a9af2cf5b5244c03d088be6d8b6978f2e90baa"
+    "3ce9f85456b51768f7b2d2261785f7680e62cdc420d0e62e41aba012a391c250d3579665ec"
+    "06a0e137c8d3da6ec07be1c2f0599dcbd1f6a801a06a062734ec34889edcd57ca99bc35d5b"
+    "9686b7fc073aa06d9d052ae7d762a7dbc5740e73ef730b478acdb54455d4db80e80b03bc61"
+    "aa013ab9c0b9ece6a00e4e46c16068a2771d0c9c42432f4ef1279481886c6cf890d656a8fa"
+    "e248c9c17bedb151ea802c3b8d7918296dc38a71f173c0b6fceb72611bc817429271ff1d1f"
+    "9fc29780727dbab824eb6ff07e552c8a6679c667bbb20925b7920c7307e3f553c64e1f8962"
+    "e556168cef58af8f406f9f6847719addd6083d19e351b2281bb6f8f64789cdab8f29915f71"
+    "128cd2152ba95124b935770dda3231973037cb7c1e8d22ee4bd10331c91d4db53c291cb16c"
+    "f498366646a27bc18df39aeb5790ba6e02c9904b0fe7e6127dd412daaafdc9b1548727eb05"
+    "57e191893e391f038797139cdf054dab4a208b00dbea79313c3952bcaf8384882456dace78"
+    "117550a133acd3cc883c036e2ecb133eaca4f6df4c002589436f529f3975fde6c779ab3038"
+    "85b1decf3f9b625dd31d634e98410486ba3e3dfff5e90da22c1734fbf9b52b92db6b44af70"
+    "da57859ca38220d8a24dca3251f9f65a1abfcbd2386732f3919c88af189efeb31ee6da9deb"
+    "f70e85bbaa928abb1d2ba86d3b038c1eea98c1a36d0e783a79e578cbc3b98d9a9f4a9c0392"
+    "bf51fcb31325c1b9131f762cd31583c231d786190dc92752781192a72ff75c3c8c297706a0"
+    "4d14571575e076dc13c8bf2c3202bb468ef6f20f6ae27ba91a0182af2c73a40477a9e1d23d"
+    "60fc5f57e9f3a86315b11ea7dc922ba70d38a24c18e1552e15239b2a29d6fc7517f5aabdd5"
+    "e0c800178beeac9b582c44af59f7c2cee341813eb13220d4bee3ef07e9ab8d35ccc0f684e9"
+    "902affb65f87cee827e6bd42fbc433df0070dc210d078fdc92fb7f559b577150e28f21f64a"
+    "c0edc61da523858e62cca0c85b8c16b8bd784f7ed8efb96314e75b3b9bd26ea93bdfc45565"
+    "85ea59cda0c92be16321ed27d93b9a05980574fc99dcb079e6145a0b0ab0c4cbebdc0e51af"
+    "2825278224922511ab721f412589b8a160fa95c3bc9038a3af4a330f5e796d30bf60017921"
+    "bc01a0200e87c26a0afedc292ff05a3e9d564323d0e0c738bcbf24f226d9aa59944abc109a"
+    "9916f57dad39fd1c928da18c32184a230be2eef814c47cea0baea02241c34fae2c8d025a02"
+    "0ab4faf8409cbc467333b807af12473f5dc3be988bb9ef61a60ff1672e07de7f5f6bf99583"
+    "f876305337ca3bbc6b2cc1f562d9f4b90cd9e54d85e04b8aa47dcb4dd5efb271f2a1d61922"
+    "cefdabcad5c3565f3f65a3e421e688b53c15a568c368eeed28d546e47dd53afc3944bfce69"
+    "94841555ac1a1968412a5504d68ae69b2067aaf3c8516a993ffb0657f82cfcb4950e6da431"
+    "de09b4a1d104e3190af9518bd2d10921ee2a3cbba8c25e1ef98606121d60cb48dbe91994f6"
+    "afceb6ea5187fdbd6d943b24c6a2584516d014ca5549828b1c5dcb80016f5dbe91667d03c0"
+    "ed9db277261ff9a7fe77886bb1c9c7d3e95e8a4204b984115323b3a8895ae102921e807294"
+    "131b5554246e6004541e11d1e449f017f1590b18c695ab79b098683f4693e0c6d87836feae"
+    "3db0bceca8b11f9b2190b8f61d77fdad0687ce678c31059af3771bc54170fad3171efa5eaa"
+    "39a4dc3d3fa837e868d1cd704de7c1877e4b77cd9fa44d500b74d0a52cf1b9c5ca6f031005"
+    "c6362066e930694a5d8063a2f27c899a78dd4f79f89e47c46e24c454efcb034105824c009f"
+    "9ce5f9b0eb6998ee1a61a2b83ed878ac81e50ffa48f6c5eaf225a56c9cbca51312808c0c51"
+    "7f49f131c12ecb7094f389228b77db2a305a01f69975138aa67dce71b80285fa1f21993189"
+    "b38898d0e2c5e6fddb644101107f610ac20ab744140addc41021fbf68b041b80fa3c1a3851"
+    "65038651ac3a07ef76368658c5a984d28e149981a7ab931e6fa1d87aa8756331927c54443a"
+    "54177cb8617bd8f54aba47a06af8f41f28cc47d71bd153d821c0c45adbad135170cfe68429"
+    "683a0bc06e4e7a06bd060a87fb8309e4f14c31a3732eada80079072e55fc26cb02ac710791"
+    "0a95d32111198ac6c07625c117acf23fefbbff59fb4c84bc6ac1a3fde905cf1d75693caaf7"
+    "7d2728e7c66d6005a236176e85cb3b282fb7a577e5e4c617c23b2af879810b560882c93552"
+    "27ee9670073d5288c4af9e57a0c81c7af0142670dbb0a18a2f79fe3ae3791739e732784600"
+    "fe9a9a4475ad985499e81ce7a06a04368fbdd007ddb2a222a0268c086252e73f18ef9b165a"
+    "c044c5f42af698b80eba1c1b4423c3b8d010d31ea85831fae7bbb74efe9a22283c1e238d09"
+    "6ae5d00ded7ae17744925d316b3d1c92861c58e1e6668dd52f4932c1e891ed5441f29786fd"
+    "d41a78b75730b8cc193ed85ac5a667a86ba4bbc1ad45aeddc56d32e16f410ad06f5cd2e6b8"
+    "2a31feb6585cfe987b8db1dc8dfdd3a4a8b09518f341fac8f8c7aeb8052cec62bf23eab8a1"
+    "b35cab3e3ed3acc3b64e29c1cc4d7cdeaefcd61f06c61b8a48b90a838ee0aac2cc76a2e56f"
+    "d8dda42e2ff863f75132ff39dd4241ac3ac1aa21845a66bdd02b77b4c38dd5ada02e3863e0"
+    "12b5bf5ad2eae7f6b1b85b4fdf960b915c257dc2be810ce92bb82c58bc478994a71332502c"
+    "ea5e5cf5bfc2ba0480d53dd2dec046f718001eba5088463e6598488dbca8cf07024102458c"
+    "abac35a14188323195f0bcc8a4d7b006467ad4ee46e6cc61f91243e311e0a775582ca3be74"
+    "9193f6044b573435eb7185c437ce3abb6b232f7d85d5beb68ebe859b9af9d6216a5c1a236c"
+    "499c661d705e9df96466429370c573b7c02d6b66c9725f39550e9bd8f63b69dd1d91ae3b7d"
+    "daf6e53f36111e43f185b2a19e6969c95441159ab96ba7928d9a8c66a81d8cb2967d90f5b8"
+    "65bf2b0986e7e10275476faf729ff6ff275347c3afb647cfaf80b76a7d51c1530e5e305241"
+    "e46f992416baa5e204ed1ccc29ab615e71ee06a21d29fabf1c114bcb0262a5031bbb8bf5d5"
+    "a4fcf004f0276eb27cb4007eb0cfc99fc515e858170e135707b07b5f0839f602d1f1ce9eb7"
+    "a41e02aea4c95a499f9ade35d8f1de41791d62ee88fac1e74828aa5025efa0444425f58edc"
+    "1158f0c1afa86f9cf062ef973eb852fe203a48a8cc6f9ef89bbd76e5602aa93c3af0cab8e0"
+    "0433b8beaf63024c36d652dfc1065c483ce480e6b36250d8bf4c3e8500ca1ab6457fa02206"
+    "6592d25f38e376a4e9d7b1dec77b378b6daf4a3e33e5aac75ff2a93808b163e738b62d6f32"
+    "c8526d92795fa623217fcb8c4450bd0ed300742327457928fb0ac0d9a1a47c490db6d3eb56"
+    "900e091c8e047e6f618acac52dea702c4ca72acd001f2c056291d71e8e7e49ea13afae0d3f"
+    "66a7d7dd8d6a264ca4be9eb02549bf40e61f1e2e4f01fe4ceafd7855686747eb1b1acd2c96"
+    "92fcedc94");
+  
+  BOOST_CHECK_EQUAL(z, w);
+}
+
+
Added: sandbox/mp_math/libs/mp_math/test/pow.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/pow.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,104 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(pow2_1, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x.pow2(0);
+  BOOST_CHECK_EQUAL(x, "1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(pow2_2, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x.pow2(1);
+  BOOST_CHECK_EQUAL(x, "2");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(pow2_3, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x.pow2(64);
+  BOOST_CHECK_EQUAL(x, "18446744073709551616");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(pow_1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("2");
+  x.pow(0);
+  BOOST_CHECK_EQUAL(x, "1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(pow_2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("2");
+  x.pow(1);
+  BOOST_CHECK_EQUAL(x, "2");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(pow_3, mp_int_type, mp_int_types)
+{
+  mp_int_type x("2");
+  x.pow(64);
+  BOOST_CHECK_EQUAL(x, "18446744073709551616");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modpow1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("2");
+  const mp_int_type exp("14");
+  const mp_int_type m("8");
+  x.modpow(exp, m);
+  BOOST_CHECK_EQUAL(x, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modpow2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("4");
+  const mp_int_type exp("13");
+  const mp_int_type m("497");
+  x.modpow(exp, m);
+  BOOST_CHECK_EQUAL(x, "445");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modpow3, mp_int_type, mp_int_types)
+{
+  mp_int_type x("2395422");
+  const mp_int_type exp("2424832");
+  const mp_int_type m("2424833");
+  x.modpow(exp, m);
+  BOOST_CHECK_EQUAL(x, "1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modpow4, mp_int_type, mp_int_types)
+{
+  mp_int_type x("184");
+  const mp_int_type exp("560");
+  const mp_int_type m("561");
+  x.modpow(exp, m);
+  BOOST_CHECK_EQUAL(x, "1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modpow5, mp_int_type, mp_int_types)
+{
+  mp_int_type x("997028168093060821869770104094480850560519901475");
+  const mp_int_type exp("7455602825647884208337395736200454918783366342656");
+  const mp_int_type m("7455602825647884208337395736200454918783366342657");
+  x.modpow(exp, m);
+  BOOST_CHECK_EQUAL(x, "1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(modpow6, mp_int_type, mp_int_types)
+{
+  mp_int_type x("184");
+  const mp_int_type exp("5600");
+  const mp_int_type m("2668");
+  x.modpow(exp, m);
+  BOOST_CHECK_EQUAL(x, "552");
+}
+
Added: sandbox/mp_math/libs/mp_math/test/prerequisite.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/prerequisite.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,39 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mp_math/mp_int.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/unique.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+//typedef boost::mp_math::mp_int_traits<boost::uint8_t, boost::uint16_t> traits_type;
+//typedef boost::mp_math::mp_int_traits<boost::uint16_t, boost::uint32_t> traits_type;
+//typedef boost::mp_math::mp_int_traits<boost::uint32_t, boost::uint64_t> traits_type;
+//typedef boost::mp_math::mp_int_traits<> traits_type;
+
+//typedef boost::mp_math::mp_int<std::allocator<void>, traits_type> mp_int_type;
+
+
+typedef boost::mpl::vector<
+  boost::mp_math::mp_int<
+    std::allocator<void>,
+    boost::mp_math::mp_int_traits<boost::uint8_t, boost::uint16_t>
+  >,
+  boost::mp_math::mp_int<
+    std::allocator<void>,
+    boost::mp_math::mp_int_traits<boost::uint16_t, boost::uint32_t>
+  >,
+  boost::mp_math::mp_int<
+    std::allocator<void>,
+    boost::mp_math::mp_int_traits<boost::uint32_t, boost::uint64_t>
+  >,
+  boost::mp_math::mp_int<>
+> some_mp_int_types;
+
+typedef boost::mpl::unique<
+  some_mp_int_types, boost::is_same<boost::mpl::_1, boost::mpl::_2>
+>::type mp_int_types;
+
+
Added: sandbox/mp_math/libs/mp_math/test/prime.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/prime.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,243 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/bind.hpp>
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+
+template<class MpInt>
+struct fixture
+{
+  std::vector<MpInt> primes;
+  std::vector<MpInt> composites;
+  std::vector<MpInt> carmichaels;
+
+  fixture();
+};
+
+template<class MpInt>
+fixture<MpInt>::fixture()
+{
+  // from http://primes.utm.edu/
+  primes.push_back("2424833");
+  primes.push_back("5915587277");
+  primes.push_back("48112959837082048697");
+  primes.push_back("671998030559713968361666935769");
+  primes.push_back("2425967623052370772757633156976982469681");
+  primes.push_back("22953686867719691230002707821868552601124472329079");
+  primes.push_back("31353958997402666638501031970734176101289470405573395248411"
+                   "3");
+  primes.push_back("46695238499321305088763925547134075213191172396379432249800"
+                   "15676156491");
+  primes.push_back("18532395500947174450709383384936679868383424444311405679463"
+                   "280782405796233163977");
+  primes.push_back("28275548353370728705475218432112134576686148069744870344385"
+                   "7012153264407439766013042402571");
+  primes.push_back("20747222467734852078216952221076085874809964747211172927529"
+                   "92589912196684750549658310084416732550077");
+  primes.push_back("35201546659608842026088328007565866231962578784643756647773"
+                   "109869245232364730066609837018108561065242031153677");
+  primes.push_back("49949091806585030192119760356408111278062369027342098434296"
+                   "86905940646121085912172293044610060051708652944665271663688"
+                   "51");
+  primes.push_back("54522121518442644531155217703627128153004567880738702606371"
+                   "72006414987479914150831821202259862091373741738511579629040"
+                   "732909194883");
+  primes.push_back("11116154175595527770308362725647119128773382144932530406518"
+                   "51655768643786825585565208246254887946100346011818823101363"
+                   "6706338524913578946637");
+  primes.push_back("65669205018189751363824155419918192392295592176092883676630"
+                   "41617905539892282237934618347035068727470717051679959727072"
+                   "53940099469869516422893633357693");
+  primes.push_back("51665668390920744584663348665715976941144605703879863575380"
+                   "48450432901440804868689337999823161841839689242893622491638"
+                   "917313351308387294478994745350551549126803");
+  primes.push_back("27218343798190233889779431662111815254174074647423987223301"
+                   "82099632472829888864333146379225493741435309651830476334589"
+                   "6749125106775048493507719412795029690510090142402163");
+  primes.push_back("27834442010031021673804244175247010833232390861821952548705"
+                   "37102073847719982865971352904187195267023851783658963402109"
+                   "57041552257518693488098683242070746473230980005141419410511"
+                   "409");
+  primes.push_back("50774619156173716518115936073898485346139106651602235699024"
+                   "04065418076795944656510340577164207672426574638345121648036"
+                   "69334456133986869450012704680852639785739151463455742734197"
+                   "2391976756821");
+  primes.push_back("58021664585639791181184025950440248398226136069516938232493"
+                   "68750582247183653682429882273371034225069773999682593823264"
+                   "19406708576245141031259861340509976971601273015479957884681"
+                   "37887651823707102007839");
+  primes.push_back("7455602825647884208337395736200454918783366342657");
+
+  // composites with small factors
+  composites.push_back("2530121");
+  
+  // composites with large factors
+  // from http://web.mit.edu/kenta/www/three/prime/composites.html.gz
+  /*composites.push_back("241999944999997");
+  composites.push_back("9247999997483999999981");
+  composites.push_back("9247999999996395999999999973");
+  composites.push_back("2738000000000000184999999999998407");
+  composites.push_back("172979999999999999711699999999999999867");
+  composites.push_back("3920000000000000000000000000000071399999999999999999999"
+                       "999999994969");
+  composites.push_back("6479999999999999999999999999999999999995877999999999999"
+                       "9999999999999999999999947559");
+  composites.push_back("1458000000000000000000000000000000000000000000000000000"
+                       "0000000006749999999999999999999999999999999999999999999"
+                       "99999999999999998367");
+  composites.push_back("1095200000000000000000000000000000000000000000000000000"
+                       "0000000000000000000000000000000003329999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "99999999999433");
+  composites.push_back("1999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999772999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999960081");
+  composites.push_back("7937999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999960"
+                       "7509999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999222"
+                       "63");
+  composites.push_back("6727999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999996154599999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "999999999999999999999999999999999999999999447193");
+  composites.push_back("4231999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999977321999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "999999999999999999999999999999999921103");
+  composites.push_back("1729799999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999383409999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "9999999999999999999999999999999999999999999999999999999"
+                       "999999610793");*/
+
+  // from http://de.wikibooks.org/wiki/Pseudoprimzahlen:_Tabelle_Carmichael-Zahlen
+  carmichaels.push_back("294409");
+  carmichaels.push_back("825265"); // 5*7*17*19*73
+  carmichaels.push_back("1152271");
+  carmichaels.push_back("23382529");
+  carmichaels.push_back("62756641");
+  carmichaels.push_back("114910489");
+  carmichaels.push_back("1407548341");
+  carmichaels.push_back("11346205609");
+  carmichaels.push_back("173032371289");
+  carmichaels.push_back("2199733160881");
+  carmichaels.push_back("84154807001953");
+  carmichaels.push_back("973694665856161");
+  carmichaels.push_back("9746347772161"); // 7*11*13*17*19*31*37*41*641
+}
+
+
+// primality tests
+BOOST_AUTO_TEST_CASE_TEMPLATE(prime_is_divisible1, mp_int_type, mp_int_types)
+{
+  using namespace boost::mp_math;
+
+  fixture<mp_int_type> f;
+  typedef typename std::vector<mp_int_type>::const_iterator iter;
+
+  for (iter i = f.primes.begin(); i != f.primes.end(); ++i)
+    BOOST_CHECK_EQUAL(is_prime(*i, primality_division_test()), true);
+  
+  for (iter i = f.composites.begin(); i != f.composites.end(); ++i)
+    BOOST_CHECK_EQUAL(is_prime(*i, primality_division_test()), false);
+}
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(prime_fermat_test1, mp_int_type, mp_int_types)
+{
+  using namespace boost;
+
+  mp_math::primality_fermat_test<
+    mp_math::uniform_mp_int<mp_int_type>
+  > fermat_test(1);
+
+  mt19937 rng;
+
+  fixture<mp_int_type> f;
+  typedef typename std::vector<mp_int_type>::const_iterator iter;
+
+  for (iter i = f.primes.begin(); i != f.primes.end(); ++i)
+    BOOST_CHECK_EQUAL(boost::mp_math::is_prime(*i, bind(fermat_test, rng, _1)), true);
+  
+  for (iter i = f.composites.begin(); i != f.composites.end(); ++i)
+    BOOST_CHECK_EQUAL(boost::mp_math::is_prime(*i, bind(fermat_test, rng, _1)), false);
+}
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(prime_miller_rabin_test1, mp_int_type, mp_int_types)
+{
+  using namespace boost;
+
+  mp_math::primality_miller_rabin_test<
+    mp_math::uniform_mp_int<mp_int_type>
+  > mr_test;
+
+  mt19937 rng;
+
+  fixture<mp_int_type> f;
+  typedef typename std::vector<mp_int_type>::const_iterator iter;
+  for (iter i = f.primes.begin(); i != f.primes.end(); ++i)
+    BOOST_CHECK_EQUAL(mp_math::is_prime(*i, bind(mr_test, rng, _1)), true);
+  
+  for (iter i = f.composites.begin(); i != f.composites.end(); ++i)
+    BOOST_CHECK_EQUAL(mp_math::is_prime(*i, bind(mr_test, rng, _1)), false);
+  
+  for (iter i = f.carmichaels.begin(); i != f.carmichaels.end(); ++i)
+    BOOST_CHECK_EQUAL(mp_math::is_prime(*i, bind(mr_test, rng, _1)), false);
+}
+
+
+// prime generation
+template<class Engine, class Distribution>
+struct tester
+{
+  boost::mp_math::primality_division_test                   test1;
+  boost::mp_math::primality_miller_rabin_test<Distribution> test2;
+  Engine rng;
+
+  explicit tester(const Engine& e) : rng(e) {}
+
+  template<class A, class T>
+  bool operator()(const boost::mp_math::mp_int<A,T>& p)
+  {
+    return test1(p) && test2(rng, p);
+  }
+};
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(generate_safe_prime_128bits, mp_int_type, mp_int_types)
+{
+  typedef tester<boost::mt19937, boost::mp_math::uniform_mp_int<mp_int_type> > tester_type;
+  typedef boost::mp_math::uniform_mp_int_bits<mp_int_type> distribution_type;
+  
+  boost::mt19937 rng;
+
+  boost::mp_math::safe_prime_generator<tester_type, distribution_type>
+    generator(128U, tester_type(rng));
+
+  const mp_int_type safe_prime = generator(rng);
+
+  BOOST_CHECK_EQUAL(safe_prime.precision(), 128U);
+}
Added: sandbox/mp_math/libs/mp_math/test/random.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/random.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,79 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int1, mp_int_type, mp_int_types)
+{
+  const mp_int_type min(0), max(128);
+  boost::mp_math::uniform_mp_int<mp_int_type> g(min, max);
+  boost::mt19937 e;
+  for (int i = 0; i < 128; ++i)
+  {
+    const mp_int_type x = g(e);
+    BOOST_REQUIRE_GE(x, min);
+    BOOST_REQUIRE_LE(x, max);
+  }
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int2, mp_int_type, mp_int_types)
+{
+  const mp_int_type min(11), max("26546549");
+  boost::mp_math::uniform_mp_int<mp_int_type> g(min, max);
+  boost::mt19937 e;
+  for (int i = 0; i < 1000; ++i)
+  {
+    const mp_int_type x = g(e);
+    BOOST_REQUIRE_GE(x, min);
+    BOOST_REQUIRE_LE(x, max);
+  }
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int_bits1, mp_int_type, mp_int_types)
+{
+  BOOST_CHECK_EQUAL(
+      boost::mp_math::uniform_mp_int_bits<mp_int_type>::has_fixed_range, false);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int_bits2, mp_int_type, mp_int_types)
+{
+  boost::mp_math::uniform_mp_int_bits<mp_int_type> g(512);
+  boost::mt19937 e;
+  const mp_int_type x = g(e);
+  BOOST_CHECK_EQUAL(x.precision(), 512U);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int_bits3, mp_int_type, mp_int_types)
+{
+  boost::mp_math::uniform_mp_int_bits<mp_int_type> g(71);
+  boost::mt19937 e;
+  const mp_int_type x = g(e);
+  BOOST_CHECK_EQUAL(x.precision(), 71U);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int_bits4, mp_int_type, mp_int_types)
+{
+  boost::mp_math::uniform_mp_int_bits<mp_int_type> g(1001);
+  boost::mt19937 e;
+  const mp_int_type x = g(e);
+  BOOST_CHECK_EQUAL(x.precision(), 1001U);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int_bits5, mp_int_type, mp_int_types)
+{
+  boost::mp_math::uniform_mp_int_bits<mp_int_type> g(8);
+  BOOST_CHECK_EQUAL(g.min(), 128U);
+  BOOST_CHECK_EQUAL(g.max(), 255U);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(uniform_mp_int_bits6, mp_int_type, mp_int_types)
+{
+  boost::mp_math::uniform_mp_int_bits<mp_int_type> g(11);
+  BOOST_CHECK_EQUAL(g.min(), 1024U);
+  BOOST_CHECK_EQUAL(g.max(), 2047U);
+}
+
+
Added: sandbox/mp_math/libs/mp_math/test/root.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/root.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,29 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqrt1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("279841");
+  const mp_int_type y = sqrt(x);
+  BOOST_CHECK_EQUAL(y, "529");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqrt2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("78310985281");
+  const mp_int_type y = sqrt(x);
+  BOOST_CHECK_EQUAL(y, "279841");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(nth_root1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("85766121");
+  const mp_int_type y = nth_root(x, 3);
+  BOOST_CHECK_EQUAL(y, "441");
+}
+
Added: sandbox/mp_math/libs/mp_math/test/serialization.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/serialization.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,27 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <sstream>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_serialization1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("0x123456789abcdef257");
+  mp_int_type y;
+
+  std::stringstream s;
+  
+  boost::archive::text_oarchive oa(s);
+  oa << x;
+  
+  boost::archive::text_iarchive ia(s);
+  ia >> y;
+
+  BOOST_CHECK_EQUAL(x, y);
+}
+
Added: sandbox/mp_math/libs/mp_math/test/shift.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/shift.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,42 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(left_shift1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("246556567891512374789511237456594795648912323213860000007849");
+  x <<= 2;
+  const mp_int_type y(
+      "986226271566049499158044949826379182595649292855440000031396");
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(left_shift2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("246556567891512374789511237456594795648912323213860000007849");
+  x <<= 99;
+  const mp_int_type y(
+      "156273790638943927367154966864556037925514287264587565911690950563681284"
+      "261029491729498112");
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(right_shift1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("246556567891512374789511237456594795648912323213860000007849");
+  x >>= 17;
+  mp_int_type y(
+      "1881077330715273855510797404911764493171022973738555908");
+  BOOST_CHECK_EQUAL(x, y);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(right_shift2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("0");
+  x >>= 17;
+  BOOST_CHECK_EQUAL(x, "0");
+}
Added: sandbox/mp_math/libs/mp_math/test/sqr.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/sqr.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,202 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqr1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("123456789");
+  const mp_int_type y = x * x;
+  BOOST_CHECK_EQUAL(y, "15241578750190521");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqr2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("25");
+  const mp_int_type y = x * x;
+  BOOST_CHECK_EQUAL(y, "625");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqr3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("300");
+  const mp_int_type y = x * x;
+  const mp_int_type z("90000");
+  BOOST_CHECK_EQUAL(y, z);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqr4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("2228218");
+  const mp_int_type y = x * x;
+  BOOST_CHECK_EQUAL(y, "4964955455524");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqr5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("999998000001");
+  const mp_int_type y = x * x;
+  const mp_int_type z("999996000005999996000001");
+  BOOST_CHECK_EQUAL(y, z);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sqr6, mp_int_type, mp_int_types)
+{
+  // this tests toom squaring and karatsuba squaring for 8, 16 and 32 bit
+  // digit_type
+  const mp_int_type x(
+    "0x5004a2519b00503006126bb044af8930502951243994250616123426085258764a856336"
+    "35702406cff061642794728883255642074744145228324022219347019013411158803532"
+    "4599404120656564868354acc9369a42721979894500607265f042a53387791b3dd4784511"
+    "50227920502852884378111055ccff50357557404795594025600468996407045934090727"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "6ca63511429296727b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e927"
+    "22c85a2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa07019a4c"
+    "1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3748f82ee78a5636"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "9464098710748f27372836255355251ae330455ffaa58681216515eeff0330517814dd7487"
+    "34682745159208158750835203309620570274592666481348052963762094268695162425"
+    "18850320172906096781969070339129822281355221058882087466637338881223511228"
+    "63144016884857141834687376804878770495858121023810198067988560350169566260"
+    "5944107067ac5771a1662497b8b93cfe57291387313365462656674328aaaaaf9067287310"
+    "ea6863ec68378827380764363420573208101547102942bf05465397209378421688020320"
+    "35702406cff061642794728883255642074744145228324022219347019013411158803532"
+    "4599404120656564868354acc9369a42721979894500607265f042a53387791b3dd4784511"
+    "50227920502852884378111055ccff50357557404795594025600468996407045934090727"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "6ca63511429296727b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e927"
+    "22c85a2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa07019a4c"
+    "1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3748f82ee78a5636"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "18850320172906096781969070339129822281355221058882087466637338881223511228"
+    "63144016884857141834687376804878770495858121023810198067988560350169566260"
+    "59441070673981642057711662497893572913873133654626566743289483229067287310"
+    "35702406cff061642794728883255642074744145228324022219347019013411158803532"
+    "4599404120656564868354acc9369a42721979894500607265f042a53387791b3dd4784511"
+    "50227920502852884378111055ccff50357557404795594025600468996407045934090727"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "6ca63511429296727b70a852e1b21384d2c6dfc53380d13650a7354766a0abb81c2c92e927"
+    "22c85a2bfe8a1a81a664bc24b8b70c76c51a3d192e819d6990624f40e3585106aa07019a4c"
+    "1161e376c082748774c34b0bcb5391c0cb34ed8aa4a5b9cca4f682e6ff3748f82ee78a5636"
+    "08041078777870387730504addbc23489bdbd45615ca892497b8b93428a2f9871374491b5c"
+    "16863866837882738076436342057320810154710294295605465397209378421688020320"
+    "0fbcfe9b5dba53956c25b59f111f1923f82a4ab1c5ed5d807aa9812835b01243185be550c7"
+    "dc372be5d7480deb1fe9bdc06a7c19bf174e49b69c1efbe47860fc19dc6240ca1cc2de92c6"
+    "f4a7484aa5cb0a9dc76f988da983e5152a831c66db00327c8bf597fc7c6e00bf3d5a791470"
+    "f84c878148cc7020890befffaa4506cebbef9a3f7c67178f2");
+
+  const mp_int_type y = x * x;
+  
+  const mp_int_type z(
+    "0x1902e5887a586c505ed49b0ef0db72e959da458fbfe7f7f1738b9da657ebc6b4f3eeda8f3"
+    "45f86a9439fb0a314af8a6d54e9002f6b9778bc217f31e1c2af869b890e50b105f2a6c8f6d4"
+    "d9f7ce008697c1ef9f6b1b3d58089517db9a209f0951f3843c9f5dd81da8082a4e79771c9fe"
+    "c7a967defed9c1d7229a9e6a78226389976caba3a3419a68d1376d7b67eb20136d1c47b480f"
+    "446428ec425ddeb779492e6e40c2318633e6783066d046486a419676066b0fcacf9c9da24ef"
+    "bb6ae2a639af668b9c732ed3ba74f4e73f28cffbc415d3a086decd149e1dd1f4265ede8666c"
+    "2963f2ef61b190fb094730110586e73afc7656f6e8e3188767ee075b98cceff2de2959b3c51"
+    "eb0cd03b5d277846536a3d5fa2baaff03d2ff90785581d170ad264d845d6e3522921afae94f"
+    "13eda75f99694a961beff0495830b53f1b282d4fc5fa665a402cc253d71aa411a16c7cf3825"
+    "6ff351d8e7f6c476d01ca3d39947a71703488cc0c85f7ce9ae7521e22ce4cb99e14dcaaaa69"
+    "d8f1390f8c8275c899e8ec14b2fb9100bd8c4e44bc2d531f049a31583e11d73070a815efad7"
+    "0e28caa18cd89a7e4bb1a17a961ae011511fe3ef495ae1c8e44653a73c6434ee77b242f7d9a"
+    "462613b92a5809da93c6d687222abf79b09a718fdf7787c7aff48b1e529da53898273abab56"
+    "00d67781a15c06e3741c79948cecbd3cd24414d40b0087844c9271bae8d470571a4e87309f9"
+    "ba510ef32c2def3e29f0f342f9a6f50fb00ee16159d0de74dfc85baf97c861a1ae63aca48b7"
+    "b2c3830ae11aa818f6da2a3cc74b5c2d0c635c9dd6d9fc5b9d35e46f8a53b93724e112a140e"
+    "cdee10eeaefa830d4678d06e1f3426abba1c9f76415ed479bee5160a8a5fcf9d5803552ca5a"
+    "810ea290fab7df557d9687af8782413fd04bf41454eae63c470ab231186c7aaf88b7e8de2ef"
+    "5e04cc8f9738f42ab5c8f993d13f8051765d4369709e54d24ec5e14138d1fe7ac81b311eb42"
+    "b0c35deebd10a3f5a60535870eeebd8662d11844ae4b39507232787d04e3c214e5b73b7b280"
+    "3395fd5a5c0c373cf2dbe76a2972e3bbaf6ff166c8134ad831ed000a4c4d5e615b74d697f8c"
+    "2be9fd8326e1aa352bcdb5ba460a0d34f750de03701e98ea43969c5b3b9de3e7bb562a320de"
+    "b10d1c8671b523611ffe7c2da353a1d3b86cf1c4d34d3347d02337e0656b9b39c8fe1f961f3"
+    "b5919df4469e895d3869590c042d6f881d9781c413613f6c5a22fd9cd24c906582e143b04b7"
+    "a09aefeed701bbf92687e995cc56578784b96c5a7a648d5c166c3b7c9a0c2df9c0166bf00b8"
+    "55c1f6e236ac96484638733eb9e84ccc4ccb33a49399e5057bd2d96ca51133496d5283a2085"
+    "56aa7f2b3264678f99f7cf5380bd61180230870ae35c00d272ec73d960ead550b29730a42a1"
+    "051e825890ec2283cf0de984af072a2125fd4ff692e47ef620b24a952c37ea379444061869c"
+    "aec75d2836afff972e54255daa9069f4c51f5bdb8ada41d3907fb5581dc7289d50577663616"
+    "464fc8b3f99676dd67bb93358a897feadd7a92336a0f4af44c9325fc53ba1d87f7b914e4847"
+    "462109cba84ad8498cd717c503d4c363b8ff405df44fa84bc9c8bed141c7f91954098b2ecb8"
+    "b59fc457ec86022bf6c395bb382f6a193e3387d52f3e1978af4576153fa7fb60d5b896cef43"
+    "e628045ec0577971b78e7ab1b3a9fa9ea6cc8e4a04f141e744f70fe0c800ce5dd3c748729c6"
+    "efa085877a7d9296ad489883ee966117e5db61bafbcd55284dc8d470646473761ec606357bb"
+    "fed899cd7c69e027656ef30b12e8a9e63868048bae95c7b67d26a843c94cec551ed5093542b"
+    "ff7437316a830e3c48f19491a81fb37aef5d89ee08b507b881e65fbf8dd3343e58b63ea3a2b"
+    "d465e02c5cb673e5c8cced17f5d3f9fad8307cd6c3abf9111e063fb197df4db52eac6092229"
+    "64e157a1b172004c1817162e688b55245c598cbdc5fd9f74db4911484feb5a390c27d0efeb3"
+    "a8bc21ff9dec02808fad5f882580facb5324a4f3a21b75c23cc311be7afe003895351fd07fa"
+    "c037d67718cc11aa5942837ee9048882e2564b625689ee3bd9487c4ec43f562508bbcd0671c"
+    "18434ca6ae92725d905210060d80e2524eb38ed600aeaf486d7b2b690a9f567d86444c35fd9"
+    "8bdf6b665dbf7e43557b281a792400274ca21fec996e5e6142780f8a7adcddbae4a2e9474a1"
+    "38931c19f96368bb2bc40aace10616bef5c975feca3c7f3e1122b41a39df9202a7a6405c647"
+    "d032f8c692e1e89838fc1dacb291d9e2d8ee90d88b6f598947d085289f9c4247548628a9e3f"
+    "6ea8ac5980e290749e39a9417b20f39dbbbed20209584a741747771020b2287007b37d17779"
+    "21303e3b7a9ee49db7b14dda965d9241548387e610758507c946eee0c49b67efaeedbe64e6b"
+    "114e3b4ddff5edd2050322d8298ae66388b1fb64435fa064364f41f129ce83a0cc563f8796e"
+    "1dd09be1a03bc5567caed9326df5714f6cf88ca247826ce93add7d17332d6870b1d0613a4fd"
+    "fd4c7d8185db385687d735d0bf22e87a045ad2a397db9c4ee0908a047f087a0fb49a27f65d0"
+    "e6e6ef0ef506d1411788ac027c29be3e93253e61ee76f951d3ce721c825bf5b883471f91f68"
+    "a37ca36d198adf93063e220a16b94e9aaca5c4691590ff2a696c1663b5ca69e3f3a11409cf9"
+    "727cf409a1f87a0a5e4805008c7488b7c9e23c42e33bfb0fab7e4f59e482ec50aa1b4d64996"
+    "4e7232c26acb75217ef1b200ebde38169d6ce7aeb2746aa29249d61af1e168a256e1848cb33"
+    "873c5457afd48194f77c786bcd8ce842605117c66b003abc05fb9b74869cc832c88df506e0e"
+    "79ebb0436443fb467269e42840a0486b3f35acca04b000876b9bf2c6a7f09ec6ff7ce198f8f"
+    "584e3e22b4a2e8279c1a043899fe0d2e5180ec1738b1cb23032374069b33a471fdd8e5f5be2"
+    "a4ff945697d9dc540878bc6a6704cb8b866914fbce94021bc2e6743dc7e160a8780912a90ff"
+    "732a81b060d97f777713881e9214474e1196ff13f07361385e19e5c5ffa24aa6b00f473cfd3"
+    "e71c42ed1c31eb9b5ec91635bf8c77e7aff696009da2163c7e1621bea9b30479a8e10906d3e"
+    "1ba06f3e64e776a62164238d18cebaf9684427fe8e5930fbd8892851c8cfa4e2c729558b909"
+    "a665f57919565d834fbebb0d64ba1721b083ca6fe55dab07546df6c1e60ab41f4836f64c27c"
+    "4f715764a472f01d947cbf8d3cd8e011129edecca4334b095edf3d37e27b7c30900eac3702c"
+    "3e09179a53462cda8dece1ecdda223d6cc32c9363f5123982b071367609b01bcfccfd4a0120"
+    "23b4dfacb5993d04434aac5a95e0192770206b4a3bdcb3a75013daedf68ed40cfca0e4bd802"
+    "4906ff8cc816d7bf556898545965b846f2b1dda3216d17d236e4ba5d2427ee799696c60297a"
+    "c720adacd63da47e2e3aeeb99c136e1b5de50cfe523823a87f94b1b4b8f6be2162ea40441dc"
+    "2f9af466c7642d0ef34429a986ae96e962e4a2cd9c12a41d71398ac03c990a15364c38a3bd9"
+    "af6605d1c9b807babd942bd66d2f6e4ccfaa2131354cf78aa09ffcec32258c9c3b53fbcc755"
+    "5bfeb11152332bef6420b08528d43f6865c5d53ade958d3b58dfe2f34391ea8d2d8fb35c32e"
+    "6a8f569d6cc9d456ff5b78fae829cc171f95f5389373a0dee3565a428237ec4e68b6e6efc3c"
+    "a5bd220699eb80bd498d2ea90d43b901881567e9c18898caea36334008b4a08e3e6cbda4e17"
+    "db7f5187d6f3284eca8c1a03faa28a2a23b27d560690642db0ea485e4be8c1c8b4441234f39"
+    "f31a6c9fe5cc7e50c777acd0746bbfb7399ee262a36a54a8ee25c334e503dcd6e00f7e9ac3a"
+    "80495156af9f9aaac62fe02c4c2373cc03d32c4be1b077d97f6167413661403a38b0df999d0"
+    "24701c5f17e5e5701cf9b9eccd9417af7637139473aab760b7ecafa863e7f049a6b98be603b"
+    "6bf0132b211b80123246c657cfdbb4b5dff7be43c364be943b5cdf03db86a6cd56a96187cb4"
+    "5b6acbf37383ca3fe7c9cc3b65a57c9ea6f4d686222801ce6d1463bb92ff5f2599619388660"
+    "99365474bbcba180f940ede8a02777bcf55d3549cfcd819aca8f055074d81af6472c3c9beaa"
+    "67b8f89066f1e02d1502aa13a4c872b9b1dc4e2a2b6d58eaa869c9e62a9f7e01efc2c87eb6a"
+    "9bc80d29c9c48a10edec1e5a799aeff2a580736525357ae40d677aa4fb6533c15b4afed1fde"
+    "f6e0e4c0a548c5be8751da42ffd8b409dcd77487437a16d769e232c95d0b780a46395ea0023"
+    "6cf19b1fafbda1c8c75aee09e06bcf0383816d0f9c364baa95a09fe2e2894693fc66166a16a"
+    "e152a24dfc5ca3646ce2cafe40a7ffbeb561ae4db74dc7ff045e85a9126a25152f0342d1f87"
+    "3ecb21bc411771eb7589f3df1be59fa97156ca5d3c93a7df10b90c525e25df36e7947614770"
+    "1f9ab2a368b179428ad005c7af2fb500fac032f0f1ff3f9694412d3c164fcc444075135fd9d"
+    "a58e2fab3ebf7b5fcaaf20256052e64b59c92db1cd3c2e0c2df41b06a540a754d349a284fa1"
+    "45a13795674240616f433d174fc67dda102db9e9e3bf23d4a8816ad130bca720ef707606206"
+    "7ab36f2061261981528dfdcaa3e21787f164e6ba318bb018f3974540ae8559790284852d31a"
+    "d8c77066f8620345f099606eced7f93e465b3a31a7b196b24e76a44d7ec6f597fb4a3a9a1a8"
+    "ba5611156e20c294b90cdde30166ee59c0c80936e992e5f3185c6396756194a7c8f1971a0b8"
+    "27477b2060dfe721fd0c2e725e25cc99d1227c6db9d5452dd70dbb0c2db67187a4e93c9bcfa"
+    "0049fad1289773ea6ffdcf6e6680a44cd577223b8f86eae3568ee5cd0b2f45a17f7b6d7531c"
+    "925e2c22b4004fd8e12ab70e2392e190dab556c0227b660cc226f5db558668bcb426a8153bc"
+    "32af18b8c7dbe3c2ad210300582f823fc5fd7aadc653c2c0b59b3e5362b158793485e56c7c4"
+    "c4");
+  
+  BOOST_CHECK_EQUAL(y, z);
+}
+
Added: sandbox/mp_math/libs/mp_math/test/stream_io.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/stream_io.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,124 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(dec_output, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  std::ostringstream os;
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "1024");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(dec_output_w_showbase, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  std::ostringstream os;
+  os.setf(std::ios_base::showbase);
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "1024");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(oct_output, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  std::ostringstream os;
+  os.setf(std::ios_base::oct, std::ios_base::basefield);
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "2000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(oct_output_w_showbase, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  std::ostringstream os;
+  os.setf(std::ios_base::oct, std::ios_base::basefield);
+  os.setf(std::ios_base::showbase);
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "02000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(hex_output, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  std::ostringstream os;
+  os.setf(std::ios_base::hex, std::ios_base::basefield);
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "400");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(hex_output_w_showbase, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  std::ostringstream os;
+  os.setf(std::ios_base::hex, std::ios_base::basefield);
+  os.setf(std::ios_base::showbase);
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "0x400");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(hex_output_w_showbase_and_uppercase, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0xabcdef0");
+  std::ostringstream os;
+  os.setf(std::ios_base::hex, std::ios_base::basefield);
+  os.setf(std::ios_base::showbase | std::ios_base::uppercase);
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "0XABCDEF0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(hex_output_w_showbase_and_showpos, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  std::ostringstream os;
+  os.setf(std::ios_base::hex, std::ios_base::basefield);
+  os.setf(std::ios_base::showbase | std::ios_base::showpos);
+  os << x;
+  BOOST_CHECK_EQUAL(os.str(), "+0x400");
+}
+
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(dec_input1, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  std::stringstream s;
+  s << "-123456";
+  s >> x;
+  BOOST_CHECK_EQUAL(x, "-123456");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(dec_input2, mp_int_type, mp_int_types)
+{
+  mp_int_type x, y;
+  std::stringstream s;
+  s << "-123456";
+  s << " " << "987654321";
+  s >> x;
+  BOOST_CHECK_EQUAL(x, "-123456");
+  BOOST_REQUIRE(s.good());
+  s >> y;
+  BOOST_CHECK_EQUAL(y, "987654321");
+  BOOST_CHECK(s.good());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(oct_input, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  std::stringstream s;
+  s << "0123456";
+  s >> x;
+  BOOST_CHECK_EQUAL(x, "0123456");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(hex_input, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  std::stringstream s;
+  s << "0xFFFFAB01";
+  s >> x;
+  BOOST_CHECK_EQUAL(x, "0xFFFFAB01");
+}
Added: sandbox/mp_math/libs/mp_math/test/string_ops.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/string_ops.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,151 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0xabcdef123456789");
+  const std::string s =
+    x.template to_string<std::string>(std::ios::hex | std::ios::showbase);
+  BOOST_CHECK_EQUAL(s, "0xabcdef123456789");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("12345678901234567890");
+  const std::string s = x.template to_string<std::string>();
+  BOOST_CHECK_EQUAL(s, "12345678901234567890");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0xabcdef123456789");
+  const std::string s = x.template to_string<std::string>(
+      std::ios::hex | std::ios::showbase | std::ios::uppercase);
+  BOOST_CHECK_EQUAL(s, "0XABCDEF123456789");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("76484675");
+  const std::string s = x.template to_string<std::string>(std::ios::oct);
+  BOOST_CHECK_EQUAL(s, "443610103");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1024");
+  const std::string s = x.template to_string<std::string>(std::ios::oct);
+  BOOST_CHECK_EQUAL(s, "2000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string6, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const std::string s =
+    x.template to_string<std::string>(
+        std::ios_base::dec | std::ios_base::showbase | std::ios_base::showpos);
+  BOOST_CHECK_EQUAL(s, "+0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string7, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0");
+  const std::string s =
+    x.template to_string<std::string>(
+        std::ios_base::oct | std::ios_base::showbase | std::ios_base::showpos);
+  BOOST_CHECK_EQUAL(s, "+0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string8, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-0");
+  const std::string s =
+    x.template to_string<std::string>(
+        std::ios_base::oct | std::ios_base::showbase | std::ios_base::showpos);
+  BOOST_CHECK_EQUAL(s, "+0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string9, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-1");
+  const std::string s =
+    x.template to_string<std::string>(
+        std::ios_base::hex | std::ios_base::showbase | std::ios_base::showpos);
+  BOOST_CHECK_EQUAL(s, "-0x1");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string10, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x95a6801ce5292b9a8410e1a59dd29967");
+  const std::string s =
+    x.template to_string<std::string>(std::ios_base::hex);
+  BOOST_CHECK_EQUAL(s, "95a6801ce5292b9a8410e1a59dd29967");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_to_string11, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0x12471fa56d6");
+  const std::string s = x.template to_string<std::string>();
+  BOOST_CHECK_EQUAL(s, "1256042682070");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_assign1, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x = "269513460";
+  BOOST_CHECK_EQUAL(x, "269513460");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_assign2, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x = "0xabcdef123456789";
+  BOOST_CHECK_EQUAL(x, "0xabcdef123456789");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_assign3, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x = "012345676543210000001";
+  BOOST_CHECK_EQUAL(x, "012345676543210000001");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_assign4, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x = "0";
+  BOOST_CHECK_EQUAL(x.is_zero(), true);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(op_assign5, mp_int_type, mp_int_types)
+{
+  mp_int_type x("0xabcedf03030303");
+  x = "-012345676543210000001";
+  BOOST_CHECK_EQUAL(x, "-012345676543210000001");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(assign1, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x.assign("123456789876543210000001", std::ios::dec);
+  BOOST_CHECK_EQUAL(x, "123456789876543210000001");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(assign2, mp_int_type, mp_int_types)
+{
+  mp_int_type x;
+  x.assign("abcdefabcdef1234567890", std::ios::hex);
+  BOOST_CHECK_EQUAL(x, "0xabcdefabcdef1234567890");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(assign3, mp_int_type, mp_int_types)
+{
+  mp_int_type x("-564897123123456456789789789897");
+  x.assign("1234567000000000000000000000000077", std::ios::oct);
+  BOOST_CHECK_EQUAL(x, "01234567000000000000000000000000077");
+}
Added: sandbox/mp_math/libs/mp_math/test/sub.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/sub.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,132 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub1, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("123456");
+  const mp_int_type y("987777");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "-864321");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub2, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("955588990000001");
+  const mp_int_type y("9801");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "955588989990200");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub3, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("99999991");
+  const mp_int_type y("987654321000123456789");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "-987654321000023456798");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub4, mp_int_type, mp_int_types)
+{
+  const mp_int_type x(
+    "49144609407766890328547643707523663509662747376486271392344480900673178645"
+    "33198519112197059826509662943577383543858946941049753393431035706592040680"
+    "43848484065292542884106550381079282660840705126574766636237650938379223350"
+    "073087806800887586256085275775217219429527000017403144");
+  const mp_int_type y(
+    "49144609407766890328547643707523663509662747376486271392344480900673178645"
+    "33198519112197059826509662943577383543858946941049753393431035706592040680"
+    "43848484065292542884106550381079282660840705126574766636237650938379223350"
+    "073087806800887586256085275775217219429527000017403144");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub5, mp_int_type, mp_int_types)
+{
+  const mp_int_type x(
+    "21665907282124706187656074325458499695895652068822763794228458103499408841");
+  const mp_int_type y(
+    "173087806800887586256085275775299999999889978789789");
+  const mp_int_type z = x - y;
+  const mp_int_type w(
+    "21665907282124706187655901237651698808309395983546988494228458213520619052");
+  BOOST_CHECK_EQUAL(z, w);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub6, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("0xff");
+  const mp_int_type y("0x1000ff0000000");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "-0x1000fefffff01");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub7, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("1000000");
+  const mp_int_type y("-1000000");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "2000000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub8, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-1000000");
+  const mp_int_type y("1000000");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "-2000000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub9, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-123456789");
+  const mp_int_type y("-123456789");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "0");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(sub10, mp_int_type, mp_int_types)
+{
+  const mp_int_type x("-1000000");
+  const mp_int_type y("-2500000");
+  const mp_int_type z = x - y;
+  BOOST_CHECK_EQUAL(z, "1500000");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(decrement1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("0");
+  for (int i = 0; i < 10; ++i)
+    --x;
+  BOOST_CHECK_EQUAL(x, "-10");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(decrement2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("4");
+  for (int i = 0; i < 10; ++i)
+    --x;
+  BOOST_CHECK_EQUAL(x, "-6");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(decrement3, mp_int_type, mp_int_types)
+{
+  mp_int_type x("-120");
+  for (int i = 0; i < 10; ++i)
+    --x;
+  BOOST_CHECK_EQUAL(x, "-130");
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(decrement4, mp_int_type, mp_int_types)
+{
+  mp_int_type x("130");
+  for (int i = 0; i < 10; ++i)
+    --x;
+  BOOST_CHECK_EQUAL(x, "120");
+}
+
Added: sandbox/mp_math/libs/mp_math/test/to_integral.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/to_integral.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,136 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include "prerequisite.hpp"
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_char1, mp_int_type, mp_int_types)
+{
+  mp_int_type x("123");
+  char z = x.template to_integral<char>();
+  BOOST_CHECK_EQUAL(z, 123);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_char2, mp_int_type, mp_int_types)
+{
+  mp_int_type x("-123");
+  char z = x.template to_integral<char>();
+  BOOST_CHECK_EQUAL(z, -123);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_char_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<char>::min());
+  char z = x.template to_integral<char>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<char>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_char_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<char>::max());
+  int z = x.template to_integral<char>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<char>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_char_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned char>::min());
+  unsigned char z = x.template to_integral<unsigned char>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned char>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_char_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned char>::max());
+  unsigned char z = x.template to_integral<unsigned char>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned char>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_int_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<int>::min());
+  int z = x.template to_integral<int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<int>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_int_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<int>::max());
+  int z = x.template to_integral<int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<int>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_int_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned int>::min());
+  unsigned int z = x.template to_integral<unsigned int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned int>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_int_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned int>::max());
+  unsigned int z = x.template to_integral<unsigned int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned int>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_long_int_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<long int>::min());
+  long int z = x.template to_integral<long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<long int>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_long_int_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<long int>::max());
+  long int z = x.template to_integral<long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<long int>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_long_int_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned long int>::min());
+  unsigned long int z = x.template to_integral<unsigned long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned long int>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_long_int_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned long int>::max());
+  unsigned long int z = x.template to_integral<unsigned long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned long int>::max());
+}
+
+#ifdef BOOST_HAS_LONG_LONG
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_long_long_int_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<long long int>::min());
+  long long int z = x.template to_integral<long long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<long long int>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_long_long_int_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<long long int>::max());
+  long long int z = x.template to_integral<long long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<long long int>::max());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_long_long_int_min, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned long long int>::min());
+  unsigned long long int z = x.template to_integral<unsigned long long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned long long int>::min());
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(to_unsigned_long_long_int_max, mp_int_type, mp_int_types)
+{
+  mp_int_type x(std::numeric_limits<unsigned long long int>::max());
+  unsigned long long int z = x.template to_integral<unsigned long long int>();
+  BOOST_CHECK_EQUAL(z, std::numeric_limits<unsigned long long int>::max());
+}
+#endif
+
Added: sandbox/mp_math/libs/mp_math/test/traits.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/test/traits.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,39 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <vector>
+#include <boost/test/unit_test.hpp>
+#include <boost/mp_math/mp_int.hpp>
+
+BOOST_AUTO_TEST_CASE(check_digit_type_and_word_type)
+{
+  typedef boost::mp_math::mp_int<> mp_int_type;
+
+  std::vector<int> x;
+  x.push_back(std::numeric_limits<unsigned char>::digits);
+  x.push_back(std::numeric_limits<unsigned short>::digits);
+  x.push_back(std::numeric_limits<unsigned int>::digits);
+  x.push_back(std::numeric_limits<unsigned long int>::digits);
+  #ifdef BOOST_HAS_LONG_LONG
+  x.push_back(std::numeric_limits<unsigned long long int>::digits);
+  #endif
+  
+  const int word_type_digits = x.back();
+
+  std::vector<int>::const_reverse_iterator it;
+  for (it = x.rbegin(); it != x.rend(); ++it)
+  {
+    if (*it <= word_type_digits / 2)
+      break;
+  }
+
+  const int digit_type_digits = *it;
+  
+  BOOST_CHECK_EQUAL(digit_type_digits,
+                    std::numeric_limits<mp_int_type::digit_type>::digits);
+  BOOST_CHECK_EQUAL(word_type_digits,
+                    std::numeric_limits<mp_int_type::word_type>::digits);
+}
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,123 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "benchmark.hpp"
+#include <iostream>
+#include <stdexcept>
+#include <boost/random.hpp>
+
+std::string create_random_hex_string(int size_in_bits)
+{
+  std::string s;
+  boost::mt19937 r;
+  boost::uniform_smallint<char> u(0,15);
+  boost::variate_generator<boost::mt19937&, boost::uniform_smallint<char> > vg(r, u);
+  // one hex digit can occupy 4 bits
+  for (int i = 0; i < size_in_bits/4; ++i)
+  {
+    char tmp = vg();
+    if (tmp < 10)
+      tmp = '0' + tmp;
+    else
+      tmp = 'a' + (tmp-10);
+    s.push_back(tmp);
+  }
+  return s;
+}
+
+std::string create_random_dec_string(int size_in_digits)
+{
+  std::string s;
+  boost::mt19937 r;
+  boost::uniform_smallint<char> u(0,9);
+  boost::variate_generator<boost::mt19937&, boost::uniform_smallint<char> > vg(r, u);
+  
+  for (int i = 0; i < size_in_digits; ++i)
+    s.push_back('0' + vg());
+  
+  return s;
+}
+
+
+const char* to_string(op_type op)
+{
+  switch (op)
+  {
+    case op_ctor_dec: return "ctor_dec";
+    case op_ctor_hex: return "ctor_hex";
+    case op_to_dec:   return "to_dec";
+    case op_to_hex:   return "to_hex";
+    case op_add:      return "add";
+    case op_subtract: return "subtract";
+    case op_multiply: return "multiply";
+    case op_divide:   return "divide";
+    case op_modulo:   return "modulo";
+    case op_square:   return "square";
+    case op_modpow:   return "modpow";
+    default:
+      return "unknown op";
+  }
+}
+
+
+benchmark_base::benchmark_base(const std::string& name, const std::string& version)
+:
+  name_(name),
+  version_(version),
+  num_input_samples_(0)
+{}
+
+benchmark_base::~benchmark_base()
+{}
+
+void benchmark_base::run(benchmark_result& r, const std::string& op, double sample_time)
+{
+  std::cout << "executing "
+            << name_ << "->" << op << " ops";
+  std::cout.flush();
+
+  if      (op == "ctor_dec") ctor_dec(r, sample_time);
+  else if (op == "ctor_hex") ctor_hex(r, sample_time);
+  else if (op == "to_dec"  ) to_dec  (r, sample_time);
+  else if (op == "to_hex"  ) to_hex  (r, sample_time);
+  else if (op == "add"     ) add     (r, sample_time);
+  else if (op == "subtract") subtract(r, sample_time);
+  else if (op == "multiply") multiply(r, sample_time);
+  else if (op == "divide"  ) divide  (r, sample_time);
+  else if (op == "modulo"  ) modulo  (r, sample_time);
+  else if (op == "square"  ) square  (r, sample_time);
+  else if (op == "modpow"  ) modpow  (r, sample_time);
+  else
+  {
+    std::cout << "unknown op: " << op << std::endl;
+    throw std::runtime_error("benchmark_base::run: unknown op");
+  }
+
+  std::cout << '\t' << r.total_time << " sec" << std::endl;
+}
+
+
+void benchmark_manager::add(const benchmark_ptr& p)
+{
+  b_.push_back(p);
+};
+
+const benchmark_ptr& benchmark_manager::get(const std::string name) const
+{
+  for (b_set::const_iterator i = b_.begin(); i != b_.end(); ++i)
+    if ((*i)->name() == name)
+      return *i;
+  throw std::runtime_error("unknown library");
+}
+
+void benchmark_manager::print_available_libs(std::ostream& out) const
+{
+  for (b_set::const_iterator it = b_.begin(); it != b_.end(); ++it)
+    out << (*it)->name() << "\n";
+}
+
+
+
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,190 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_TOOLS_BENCHMARK_HPP
+#define BOOST_MP_MATH_TOOLS_BENCHMARK_HPP
+
+#include <string>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <boost/timer.hpp>
+
+
+std::string create_random_hex_string(int size_in_bits);
+std::string create_random_dec_string(int size_in_digits);
+
+
+enum op_type
+{
+  op_ctor_dec,
+  op_ctor_hex,
+  op_to_dec,
+  op_to_hex,
+  op_add,
+  op_subtract,
+  op_multiply,
+  op_divide,
+  op_modulo,
+  op_square,
+  op_modpow
+};
+
+const char* to_string(op_type op);
+
+
+struct benchmark_result
+{
+  std::string libname;
+  std::string op;
+
+  double        sample_time;
+  double        total_time;
+  // time for a single op execution in milliseconds
+  std::vector<double> ops;
+
+  bool operator < (const benchmark_result& r) const { return op < r.op; }
+
+  void clear()
+  {
+    total_time = 0;
+    ops.clear();
+  }
+};
+
+
+struct benchmark_base
+{
+  typedef std::vector<std::string> string_vec;
+
+  benchmark_base(const std::string& name, const std::string& version);
+  
+  virtual ~benchmark_base();
+
+  virtual void set_num_input_samples(unsigned int num)
+  {
+    num_input_samples_ = num;
+  }
+  
+  void run(benchmark_result& r, const std::string& op, double sample_time);
+
+  // these need to be invoked because we need these for all other benchmarks
+  virtual void construct_operand_1(const std::string& src, unsigned int i) = 0;
+  virtual void construct_operand_2(const std::string& src, unsigned int i) = 0;
+
+  //virtual bool has_op(op_type) = 0;
+
+  // now come the individual benchmarks
+  virtual void ctor_dec(benchmark_result&, double sample_time) = 0;
+  virtual void ctor_hex(benchmark_result&, double sample_time) = 0;
+  virtual void to_dec  (benchmark_result&, double sample_time) = 0;
+  virtual void to_hex  (benchmark_result&, double sample_time) = 0;
+  virtual void add     (benchmark_result&, double sample_time) = 0;
+  virtual void subtract(benchmark_result&, double sample_time) = 0;
+  virtual void multiply(benchmark_result&, double sample_time) = 0;
+  virtual void divide  (benchmark_result&, double sample_time) = 0;
+  virtual void modulo  (benchmark_result&, double sample_time) = 0;
+  virtual void square  (benchmark_result&, double sample_time) = 0;
+  virtual void modpow  (benchmark_result&, double sample_time) = 0;
+
+  const std::string& name   () const { return name_;    }
+  const std::string& version() const { return version_; }
+
+  string_vec dec_str; // inputs for ctor_dec
+  string_vec hex_str; // inputs for ctor_hex
+
+protected:
+
+  const std::string name_;
+  const std::string version_;
+  unsigned int      num_input_samples_;
+};
+
+
+template<class MPInt>
+struct benchmark
+:
+  benchmark_base
+{
+  typedef MPInt mp_int_type;
+  typedef std::vector<mp_int_type> mp_int_vec;
+
+  benchmark(const std::string& name, const std::string& version)
+  :
+    benchmark_base(name, version)
+  {}
+
+  virtual ~benchmark();
+
+  virtual void clear_dst_vector() = 0;
+
+  virtual void set_num_input_samples(unsigned int num);
+
+  template<class F>
+  void do_bench(F f, benchmark_result& r, double sample_time);
+  template<class F>
+  void do_bench2(F f, benchmark_result& r, double sample_time);
+
+  mp_int_vec dst;   // destination vector
+  mp_int_vec src1;  // operand 1 vector
+  mp_int_vec src2;  // operand 2 vector
+  std::string str; // holds result of to_dec, to_hex string conversions
+};
+
+
+template<class MPInt>
+benchmark<MPInt>::~benchmark()
+{}
+
+template<class MPInt>
+void benchmark<MPInt>::set_num_input_samples(unsigned int num)
+{
+  dst.resize(num);
+  src1.resize(num);
+  src2.resize(num);
+  benchmark_base::set_num_input_samples(num);
+}
+
+template<class MPInt>
+template<class BenchFunctor>
+void benchmark<MPInt>::do_bench(BenchFunctor f, benchmark_result& r, double sample_time)
+{
+  boost::timer total;
+  boost::timer op_time;
+  for (unsigned int i = 0; i < num_input_samples_; ++i)
+  {
+    unsigned long num_ops_executed = 0;
+    op_time.restart();
+    for (; op_time.elapsed() < sample_time; ++num_ops_executed)
+      f(i);
+    // push the number of ops per millisecond
+    r.ops.push_back(1.0/(op_time.elapsed() * 1000.0 / num_ops_executed));
+  }
+  r.total_time = total.elapsed();
+  // clear dst vector for next test
+  clear_dst_vector();
+}
+
+
+typedef boost::shared_ptr<benchmark_base> benchmark_ptr;
+
+
+// This class simply holds all available benchmark libraries
+struct benchmark_manager
+{
+  typedef std::vector<benchmark_ptr> b_set;
+  
+  void add(const benchmark_ptr& p);
+
+  const benchmark_ptr& get(const std::string name) const;
+
+  void print_available_libs(std::ostream& out) const;
+
+  b_set b_;
+};
+
+
+
+#endif
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,53 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "benchmark_gmp.hpp"
+#include <boost/timer.hpp>
+
+benchmark_gmp::benchmark_gmp()
+:
+  base(std::string("gmp"), gmp_version)
+{
+  // init dst vector
+  std::fill(dst.begin(), dst.end(), mpz_class());
+}
+
+benchmark_gmp::~benchmark_gmp()
+{}
+
+void benchmark_gmp::clear_dst_vector()
+{
+  std::fill(dst.begin(), dst.end(), mpz_class());
+}
+
+void benchmark_gmp::construct_operand_1(const std::string& src, unsigned int i)
+{
+  src1[i] = mpz_class(src, 16);
+}
+
+void benchmark_gmp::construct_operand_2(const std::string& src, unsigned int i)
+{
+  src2[i] = mpz_class(src, 16);
+}
+
+#define bench_function_def(f)                                   \
+void benchmark_gmp::f(benchmark_result& r, double sample_time)  \
+{ do_bench(f##_op(*this), r, sample_time); }
+
+bench_function_def(ctor_dec)
+bench_function_def(ctor_hex)
+bench_function_def(to_dec)
+bench_function_def(to_hex)
+bench_function_def(add)
+bench_function_def(subtract)
+bench_function_def(multiply)
+bench_function_def(divide)
+bench_function_def(modulo)
+bench_function_def(square)
+bench_function_def(modpow)
+
+#undef bench_function_def
+
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,107 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_TOOLS_BENCHMARK_GMP_HPP
+#define BOOST_MP_MATH_TOOLS_BENCHMARK_GMP_HPP
+
+#include <gmpxx.h>
+#include "benchmark.hpp"
+
+
+struct benchmark_gmp : benchmark<mpz_class>
+{
+  typedef benchmark<mpz_class> base;
+
+  benchmark_gmp();
+  ~benchmark_gmp();
+
+  void clear_dst_vector();
+
+  void construct_operand_1(const std::string& src, unsigned int i);
+  void construct_operand_2(const std::string& src, unsigned int i);
+
+  void ctor_dec(benchmark_result&, double sample_time);
+  void ctor_hex(benchmark_result&, double sample_time);
+  void to_dec  (benchmark_result&, double sample_time);
+  void to_hex  (benchmark_result&, double sample_time);
+  void add     (benchmark_result&, double sample_time);
+  void subtract(benchmark_result&, double sample_time);
+  void multiply(benchmark_result&, double sample_time);
+  void divide  (benchmark_result&, double sample_time);
+  void modulo  (benchmark_result&, double sample_time);
+  void square  (benchmark_result&, double sample_time);
+  void modpow  (benchmark_result&, double sample_time);
+
+  struct ctor_dec_op
+  {
+    base& b;
+    explicit ctor_dec_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.dst[i] = mpz_class(b.dec_str[i], 10); }
+  };
+
+  struct ctor_hex_op
+  {
+    base& b;
+    explicit ctor_hex_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.dst[i] = mpz_class(b.hex_str[i], 16); }
+  };
+
+  struct to_dec_op
+  {
+    base& b;
+    explicit to_dec_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.str = b.src1[i].get_str(10); }
+  };
+
+  struct to_hex_op
+  {
+    base& b;
+    explicit to_hex_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.str = b.src1[i].get_str(16); }
+  };
+
+  #define bench_functor(name,op)              \
+  struct name##_op {                          \
+    base& b;                                  \
+    explicit name##_op(base& ba) : b(ba) {}   \
+    void operator()(unsigned int i) const     \
+    { b.dst[i] = b.src1[i] op b.src2[i]; }    \
+  }
+
+  bench_functor(add,+);
+  bench_functor(subtract,-);
+  bench_functor(multiply,*);
+  bench_functor(divide,/);
+  bench_functor(modulo,%);
+
+  #undef bench_functor
+
+  struct square_op
+  {
+    base& b;
+    explicit square_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const
+    {
+      mpz_pow_ui(b.dst[i].get_mpz_t(), b.src1[i].get_mpz_t(), 2);
+    }
+  };
+
+  struct modpow_op
+  {
+    base& b;
+    explicit modpow_op(base& ba) : b (ba) {}
+    void operator()(unsigned int i) const
+    {
+      mpz_powm(
+          b.dst[i].get_mpz_t(),
+          b.src1[i].get_mpz_t(), b.src1[i].get_mpz_t(), b.src2[i].get_mpz_t());
+    }
+  };
+};
+
+
+
+#endif
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_libtom.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_libtom.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,65 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "benchmark_libtom.hpp"
+
+const char* ltm_version = "0.41";
+
+benchmark_libtom::benchmark_libtom()
+:
+  base("libtommath", ltm_version)
+{
+  // init vectors
+  for (mp_int_vec::iterator it = dst.begin(); it != dst.end(); ++it)
+    mp_init(&*it);
+  for (mp_int_vec::iterator it = src1.begin(); it != src1.end(); ++it)
+    mp_init(&*it);
+  for (mp_int_vec::iterator it = src2.begin(); it != src2.end(); ++it)
+    mp_init(&*it);
+}
+
+benchmark_libtom::~benchmark_libtom()
+{
+  for (mp_int_vec::iterator it = dst.begin(); it != dst.end(); ++it)
+    mp_clear(&*it);
+}
+
+void benchmark_libtom::clear_dst_vector()
+{
+  for (mp_int_vec::iterator it = dst.begin(); it != dst.end(); ++it)  
+  {                                                                     
+    mp_clear(&*it);                                                     
+    mp_init(&*it);                                                      
+  }
+}
+
+void benchmark_libtom::construct_operand_1(const std::string& src, unsigned int i)
+{
+  mp_read_radix(&src1[i], src.c_str(), 16);
+}
+
+void benchmark_libtom::construct_operand_2(const std::string& src, unsigned int i)
+{
+  mp_read_radix(&src2[i], src.c_str(), 16);
+}
+
+#define bench_function_def(f)                                      \
+void benchmark_libtom::f(benchmark_result& r, double sample_time)  \
+{ do_bench(f##_op(*this), r, sample_time); }
+
+bench_function_def(ctor_dec)
+bench_function_def(ctor_hex)
+bench_function_def(to_dec)
+bench_function_def(to_hex)
+bench_function_def(add)
+bench_function_def(subtract)
+bench_function_def(multiply)
+bench_function_def(divide)
+bench_function_def(modulo)
+bench_function_def(square)
+bench_function_def(modpow)
+
+#undef bench_function_def
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_libtom.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_libtom.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,132 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_TOOLS_BENCHMARK_LIBTOM_HPP
+#define BOOST_MP_MATH_TOOLS_BENCHMARK_LIBTOM_HPP
+
+#include "benchmark.hpp"
+#include "tommath.h"
+
+extern const char* ltm_version;
+
+struct benchmark_libtom : benchmark<mp_int>
+{
+  typedef benchmark<mp_int> base;
+
+  benchmark_libtom();
+  ~benchmark_libtom();
+
+  void clear_dst_vector();
+
+  void construct_operand_1(const std::string& src, unsigned int i);
+  void construct_operand_2(const std::string& src, unsigned int i);
+
+  void ctor_dec(benchmark_result&, double sample_time);
+  void ctor_hex(benchmark_result&, double sample_time);
+  void to_dec  (benchmark_result&, double sample_time);
+  void to_hex  (benchmark_result&, double sample_time);
+  void add     (benchmark_result&, double sample_time);
+  void subtract(benchmark_result&, double sample_time);
+  void multiply(benchmark_result&, double sample_time);
+  void divide  (benchmark_result&, double sample_time);
+  void modulo  (benchmark_result&, double sample_time);
+  void square  (benchmark_result&, double sample_time);
+  void modpow  (benchmark_result&, double sample_time);
+
+  struct ctor_dec_op
+  {
+    base& b;
+    explicit ctor_dec_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { mp_read_radix(&b.dst[i], b.dec_str[i].c_str(), 10); }
+  };
+
+  struct ctor_hex_op
+  {
+    base& b;
+    explicit ctor_hex_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { mp_read_radix(&b.dst[i], b.hex_str[i].c_str(), 16); }
+  };
+
+  struct to_dec_op
+  {
+    base& b;
+    char* tmp;
+    unsigned size;
+    
+    explicit to_dec_op(base& ba) : b(ba), tmp(0), size(0) {}
+    ~to_dec_op() { delete[] tmp; }
+    
+    void operator()(unsigned int i)
+    {
+      const unsigned needed = b.src1[i].used * DIGIT_BIT / 3;
+      if (size < needed)
+        tmp = new char[needed];
+      mp_toradix(&b.src1[i], tmp, 10);
+      b.str = tmp;
+    }
+  };
+
+  struct to_hex_op
+  {
+    base& b;
+    char* tmp;
+    unsigned size;
+    
+    explicit to_hex_op(base& ba) : b(ba), tmp(0), size(0) {}
+    ~to_hex_op() { delete[] tmp; }
+    
+    void operator()(unsigned int i)
+    {
+      const unsigned needed = b.src1[i].used * DIGIT_BIT / 4 + 1;
+      if (size < needed)
+        tmp = new char[needed];
+      mp_toradix(&b.src1[i], tmp, 16);
+      b.str = tmp;
+    }
+  };
+
+  static void mp_div_wrapper(mp_int* x, mp_int* y, mp_int* dst)
+  {
+    mp_div(x, y, dst, NULL);
+  }
+
+  #define bench_functor(name,op,func)           \
+  struct name##_op {                            \
+    base& b;                                    \
+    explicit name##_op(base& ba) : b(ba) {}     \
+    void operator()(unsigned int i) const       \
+    { func(&b.src1[i],&b.src2[i],&b.dst[i]); }  \
+  }
+  
+  bench_functor(add,+,mp_add);
+  bench_functor(subtract,-,mp_sub);
+  bench_functor(multiply,*,mp_mul);
+  bench_functor(divide,/,mp_div_wrapper);
+  bench_functor(modulo,%,mp_mod);
+
+  #undef bench_functor
+
+  struct square_op
+  {
+    base& b;
+    explicit square_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { mp_sqr(&b.src1[i], &b.dst[i]); }
+  };
+
+  struct modpow_op
+  {
+    base& b;
+    explicit modpow_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const
+    {
+      mp_exptmod(&b.src1[i], &b.src1[i], &b.src2[i], &b.dst[i]);
+    }
+  };
+};
+
+
+
+#endif
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_mp_math.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_mp_math.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,53 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/version.hpp>
+#include "benchmark_mp_math.hpp"
+
+
+benchmark_mp_math::benchmark_mp_math()
+:
+  base("boost.mp_math", BOOST_LIB_VERSION)
+{
+  // init dst vector
+  std::fill(dst.begin(), dst.end(), mp_int_type());
+}
+
+benchmark_mp_math::~benchmark_mp_math()
+{}
+
+void benchmark_mp_math::clear_dst_vector()
+{
+  std::fill(dst.begin(), dst.end(), mp_int_type());
+}
+
+void benchmark_mp_math::construct_operand_1(const std::string& src, unsigned int i)
+{
+  src1[i].assign(src, std::ios::hex);
+}
+
+void benchmark_mp_math::construct_operand_2(const std::string& src, unsigned int i)
+{
+  src2[i].assign(src, std::ios::hex);
+}
+
+#define bench_function_def(f)                                       \
+void benchmark_mp_math::f(benchmark_result& r, double sample_time)  \
+{ do_bench(f##_op(*this), r, sample_time); }
+
+bench_function_def(ctor_dec)
+bench_function_def(ctor_hex)
+bench_function_def(to_dec)
+bench_function_def(to_hex)
+bench_function_def(add)
+bench_function_def(subtract)
+bench_function_def(multiply)
+bench_function_def(divide)
+bench_function_def(modulo)
+bench_function_def(square)
+bench_function_def(modpow)
+
+#undef bench_function_def
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_mp_math.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_mp_math.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,106 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_TOOLS_BENCHMARK_MP_MATH_HPP
+#define BOOST_MP_MATH_TOOLS_BENCHMARK_MP_MATH_HPP
+
+#include <boost/mp_math/mp_int.hpp>
+#include "benchmark.hpp"
+
+
+struct benchmark_mp_math : benchmark<boost::mp_math::mp_int<> >
+{
+  typedef benchmark<boost::mp_math::mp_int<> > base;
+
+  benchmark_mp_math();
+  virtual ~benchmark_mp_math();
+
+  void clear_dst_vector();
+
+  void construct_operand_1(const std::string& src, unsigned int i);
+  void construct_operand_2(const std::string& src, unsigned int i);
+
+  void ctor_dec(benchmark_result&, double sample_time);
+  void ctor_hex(benchmark_result&, double sample_time);
+  void to_dec  (benchmark_result&, double sample_time);
+  void to_hex  (benchmark_result&, double sample_time);
+  void add     (benchmark_result&, double sample_time);
+  void subtract(benchmark_result&, double sample_time);
+  void multiply(benchmark_result&, double sample_time);
+  void divide  (benchmark_result&, double sample_time);
+  void modulo  (benchmark_result&, double sample_time);
+  void square  (benchmark_result&, double sample_time);
+  void modpow  (benchmark_result&, double sample_time);
+
+  struct ctor_dec_op
+  {
+    base& b;
+    explicit ctor_dec_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.dst[i].assign(b.dec_str[i], std::ios::dec); }
+  };
+
+  struct ctor_hex_op
+  {
+    base& b;
+    explicit ctor_hex_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.dst[i].assign(b.hex_str[i], std::ios::hex); }
+  };
+
+  struct to_dec_op
+  {
+    base& b;
+    explicit to_dec_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.str = b.src1[i].to_string<std::string>(std::ios::dec); }
+  };
+
+  struct to_hex_op
+  {
+    base& b;
+    explicit to_hex_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const { b.str = b.src1[i].to_string<std::string>(std::ios::hex); }
+  };
+
+  #define bench_functor(name,op)              \
+  struct name##_op {                          \
+    base& b;                                  \
+    explicit name##_op(base& ba) : b(ba) {}   \
+    void operator()(unsigned int i) const     \
+    { b.dst[i] = b.src1[i]; b.dst[i] op##= b.src2[i]; } \
+  }
+
+  bench_functor(add,+);
+  bench_functor(subtract,-);
+  bench_functor(multiply,*);
+  bench_functor(divide,/);
+  bench_functor(modulo,%);
+
+  #undef bench_functor
+
+  struct square_op
+  {
+    base& b;
+    explicit square_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const
+    {
+      b.dst[i] = b.src1[i];
+      b.dst[i].sqr();
+    }
+  };
+
+  struct modpow_op
+  {
+    base& b;
+    explicit modpow_op(base& ba) : b(ba) {}
+    void operator()(unsigned int i) const
+    {
+      b.dst[i] = boost::mp_math::modpow(b.src1[i], b.src1[i], b.src2[i]);
+    }
+  };
+};
+
+
+
+#endif
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_result.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,85 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+
+
+struct benchmark_result
+{
+  std::string libname;
+  std::string op;
+
+  double        total_time;
+  unsigned long total_ops;
+  std::vector<unsigned long> ops;
+
+  bool operator < (const benchmark_result& r) const { return op < r.op; }
+
+  void clear()
+  {}
+};
+
+
+
+struct benchmark_summary
+{
+  typedef std::vector<std::string> string_list;
+  // TODO need a list and a set view of op_result
+  typedef std::set<benchmark_result>         result_list;
+  typedef result_list::const_iterator const_result_iterator;
+
+
+  result_list results;
+
+  void write_data_files(const string_list&);
+  void write_gnuplot_scripts();
+  void write_summary_file();
+
+  bool results_for_op_exist(const std::string& opname) const;
+};
+
+
+
+void benchmark_summary::write_data_files(const string_list& ops) const
+{
+  typedef std::vector<std::string> string_list;
+  for (string_list::const_iterator op = ops.begin(); op != ops.end(); ++op)
+  {
+    if (!results_for_op_exist(op))
+      continue;
+
+    const std::string filename(std::string(to_string(op)) + ".dat");
+    std::ofstream file(filename.c_str());
+    if (!file.is_open())
+      throw std::runtime_error("couldn't open data file");
+
+    const unsigned int num_ops = results.count(op);
+    const_result_iterator first = results.lower_bound(op);
+    const_result_iterator last = results.upper_bound(op);
+
+    for (unsigned int i = 0; i < num_input_samples_; ++i)
+    {
+      while (first != last)
+      {
+        file << first->ops.at(i);
+        
+        if (++first != last)
+          file << "\t";
+      }
+      file << "\n";
+    }
+  }
+}
+
+bool benchmark_summary::results_for_op_exist(const std::string& opname) const
+{
+  return results.find(benchmark_result("", opname)) != results.end();
+}
+
+
+
+
+benchmark_runner::get_benchmark_result();
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,350 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cmath>
+#include <fstream>
+#include <iostream>
+#include <numeric> // accumulate
+#include <stdexcept>
+#include <sstream>
+#include "benchmark_runner.hpp"
+
+
+void benchmark_runner::run(const std::vector<std::string>& ops,
+                           double sample_time)
+{
+  init_libs();
+
+  for (std::vector<std::string>::const_iterator op = ops.begin(); op != ops.end(); ++op)
+    execute_bench_op(*op, sample_time);
+
+  std::cout << "creating data files..." << std::endl;
+  create_data_files();
+}
+
+unsigned long
+benchmark_runner::get_operand1_size(unsigned int sample_number) const
+{
+  // linear growth
+  const double m = static_cast<double>(end_ - beg_) /
+                   static_cast<double>(num_input_samples_);
+  return (m * sample_number) + beg_;
+}
+
+unsigned long
+benchmark_runner::get_operand2_size(unsigned int sample_number) const
+{
+  // modified sine curve
+  const double pi = 3.141592654;
+  const double sample_num_to_rad = num_input_samples_ / (4.5 * pi);
+  
+  // scale sample_number into the range [0...4.5*PI]
+  const double x = sample_number / sample_num_to_rad;
+
+  const double y_val = std::sin(x) + 1.0;
+
+  const double y_top = get_operand1_size(sample_number);
+  const double p0 = pi;
+  double y_bottom;
+  if (x <= p0)
+    y_bottom = y_top / (x / p0 * 2.0 + 1.0) + 1.0;
+  else
+    y_bottom = y_top / 3.0;
+
+  // we want to scale the curve at the point p1 to be above y_top at x = 2.5*pi
+  const double p1 = 2.5 * pi;
+  
+  // here we use a function of the form y = -ax^2 + b to scale the curve at (and
+  // around) p1
+  const double a = 1.0/(p1 * p1);
+  double adjust = -a * ((x-p1) * (x-p1)) + 1.0;
+  // scale to be 10% above p1
+  adjust *= 1.1;
+  // stop scaling once we're past p1 and 'adjust' falls below 1.0
+  if (x > p1 && adjust < 1.0)
+    adjust = 1.0;
+  
+  return static_cast<unsigned long>(y_bottom * adjust * y_val + y_bottom);
+}
+
+benchmark_runner::benchmark_runner(unsigned int num_input_samples,
+                                   unsigned long operand_size_beg,
+                                   unsigned long operand_size_end)
+:
+  num_input_samples_(num_input_samples),
+  beg_(operand_size_beg ? operand_size_beg : 1), // zero length not allowed
+  end_(operand_size_end)
+{
+}
+
+void benchmark_runner::add_library(const boost::shared_ptr<benchmark_base>& b)
+{
+  libs_.push_back(b);
+}
+
+void benchmark_runner::create_input_vectors(unsigned long min, unsigned long max)
+{
+  std::ofstream iv_file("input_vecs.dat");
+  if (!iv_file.is_open())
+    throw std::runtime_error("couldn't open file input_vecs.dat");
+
+  std::cout << "Creating " << num_input_samples_
+            << " operand indices for numbers between "
+            << min << " and " << max << " bits."
+            << std::endl;
+  
+  const std::string rn = create_random_hex_string(max);
+
+  std::cout << "creating input vectors";
+  std::cout.flush();
+
+  // create input vector where number size is determined by the sine function
+  const unsigned int stepsize = num_input_samples_ / 10;
+  for (unsigned int i = 0; i < num_input_samples_; ++i)
+  {
+    const unsigned long size1 = get_operand1_size(i);
+    const unsigned long size2 = get_operand2_size(i);
+
+    // divide by 4 because rn has max/4 hex digits
+    string_vec1_.push_back(rn.substr(0, size1/4));
+    string_vec2_.push_back(rn.substr(0, size2/4));
+    
+    // output the input sizes for a graph here
+    iv_file << size1 << "\t" << size2 << "\n";
+    
+    if (((i+1) % stepsize) == 0)
+    {
+      std::cout << ".";
+      std::cout.flush();
+    }      
+  }
+
+  std::cout << std::endl;
+
+  iv_file.close();
+}
+
+void benchmark_runner::write_input_vector_plotfile(unsigned int x, unsigned int y) const
+{
+  std::ofstream pf("input_vecs.plt");
+  if (!pf.is_open())
+    throw std::runtime_error("couldn't open plotfile");
+  pf << "set term png size " << x << "," << y << "\n"
+        "set output \"input_vecs.png\"\n"
+        "set title \"input size of operands\"\n"
+        "set key left\n"
+        "set xlabel \"operand number\"\n"
+        "set ylabel \"size in bits\"\n"
+        "plot \"input_vecs.dat\" using 0:1 title \"operand 1 size\" with lines,\\\n"
+        "     \"input_vecs.dat\" using 0:2 title \"operand 2 size\" with lines";
+}
+
+void benchmark_runner::init_libs()
+{
+  const unsigned long min_size = 
+    std::min(get_operand1_size(0),
+             get_operand2_size(0));
+  
+  const unsigned long max_size = 
+    std::max(get_operand1_size(num_input_samples_),
+             get_operand2_size(num_input_samples_));
+
+  create_input_vectors(min_size, max_size);
+
+  const unsigned int stepsize = num_input_samples_ / 10;
+  for (library_vec::iterator lib = libs_.begin(); lib != libs_.end(); ++lib)
+  {
+    (*lib)->set_num_input_samples(num_input_samples_);
+    
+    // init ctor strings
+    std::string hex_s = create_random_hex_string(max_size);
+    std::string dec_s = create_random_dec_string(max_size);
+
+    for (unsigned int i = 0; i < num_input_samples_; ++i)
+    {
+      (*lib)->hex_str.push_back(hex_s.substr(0, get_operand1_size(i)/4));
+      (*lib)->dec_str.push_back(dec_s.substr(0, get_operand1_size(i)));
+    }
+
+    
+    std::cout << (*lib)->name() << "->"
+              << "constructing operand 1 input vector";
+    std::cout.flush();
+
+    for (unsigned int i = 0; i < num_input_samples_; ++i)
+    {
+      (*lib)->construct_operand_1(string_vec1_[i], i);
+      if (((i+1) % stepsize) == 0)
+      {
+        std::cout << ".";
+        std::cout.flush();
+      }
+    }
+    std::cout << std::endl;
+
+    std::cout << (*lib)->name() << "->"
+              << "constructing operand 2 input vector";
+    std::cout.flush();
+
+    for (unsigned int i = 0; i < num_input_samples_; ++i)
+    {
+      (*lib)->construct_operand_2(string_vec2_[i], i);
+      if (((i+1) % stepsize) == 0)
+      {
+        std::cout << ".";
+        std::cout.flush();
+      }
+    }
+    std::cout << std::endl;
+  }
+}
+
+void benchmark_runner::execute_bench_op(const std::string& op, double sample_time)
+{
+  for (library_vec::iterator lib = libs_.begin(); lib != libs_.end(); ++lib)
+  {
+    benchmark_result r;
+    
+    r.libname = (*lib)->name() + "-" + (*lib)->version();
+    r.op = op;
+    r.sample_time = sample_time;
+
+    (*lib)->run(r, op, sample_time);
+
+    results_.push_back(r);
+  }
+}
+
+void benchmark_runner::create_data_files()
+{
+  result_list::const_iterator r = results_.begin();
+  
+  // expects result list to be sorted by op name
+  while (r != results_.end())
+  {
+    data_file d;
+    result_list::const_iterator cur = r;
+    while (r != results_.end() && r->op == cur->op)
+    {
+      data_file::column c;
+
+      c.libname = r->libname;
+      c.data = r->ops;
+      
+      // scale from ops per sample_time_ to ops per second
+      /*const double scale = 1.0 / r->sample_time;
+      for (std::vector<double>::iterator it = c.data.begin();
+          it != c.data.end(); ++it)
+        *it *= scale;*/
+
+      c.total_ops = std::accumulate(r->ops.begin(), r->ops.end(), 0.);
+      d.cols.push_back(c);
+      ++r;
+    }
+
+    d.op = cur->op;
+
+    d.cols.sort();
+    dfiles_.push_back(d);
+  }
+}
+
+void benchmark_runner::write_data_files() const
+{
+  for (std::list<data_file>::const_iterator it = dfiles_.begin();
+      it != dfiles_.end(); ++it)
+    it->write();
+}
+
+void benchmark_runner::write_gnuplot_scripts(unsigned int x, unsigned int y) const
+{
+  write_input_vector_plotfile(x, y);
+  for (std::list<data_file>::const_iterator it = dfiles_.begin();
+      it != dfiles_.end(); ++it)
+    it->write_gnuplot_script(x, y);
+}
+
+void benchmark_runner::write_summary_file() const
+{
+  std::ostringstream s;
+  for (std::list<data_file>::const_iterator d = dfiles_.begin();
+      d != dfiles_.end(); ++d)
+  {
+    s << d->op << "\n";
+    for (std::list<data_file::column>::const_iterator c = d->cols.begin();
+        c != d->cols.end(); ++ c)
+    {
+      s << c->libname << " total ops = " << c->total_ops << "\n";
+    }
+  }
+
+  std::cout << s.str();
+
+  std::ofstream file("summary.txt");
+  if (!file.is_open())
+    throw std::runtime_error("couldn't open summary.txt file");
+  file << s.str();
+}
+
+void benchmark_runner::write_results(unsigned int x, unsigned int y) const
+{
+  std::cout << "writing data files..." << std::endl;
+  write_data_files();
+  std::cout << "writing gnuplot scripts..." << std::endl;
+  write_gnuplot_scripts(x, y);
+  write_summary_file();
+}
+
+
+void data_file::write() const
+{
+  const std::string filename(op + ".dat");
+  std::ofstream file(filename.c_str());
+  if (!file.is_open())
+    throw std::runtime_error("couldn't open data file");
+
+  const unsigned int col_len = cols.front().data.size();
+  for (unsigned int i = 0; i < col_len; ++i)
+  {
+    std::list<column>::const_iterator it = cols.begin();
+    
+    while (it != cols.end())
+    {
+      file << it->data.at(i);
+        
+      if (++it != cols.end())
+        file << "\t";
+    }
+    file << "\n";
+  }
+}
+
+void data_file::write_gnuplot_script(unsigned int x, unsigned int y) const
+{
+  const std::string filename(op + ".plt");
+  std::ofstream file(filename.c_str());
+  if (!file.is_open())
+    throw std::runtime_error("couldn't open plot file");
+
+  file << "set title \"" << op << "\"\n"
+          "set xlabel " << "\"operand index\"\n"
+          "set ylabel " << "\"ops/msec\"\n"
+          "set autoscale\n"
+          "set term png size " << x << "," << y << "\n"
+          "set output \"" << op << ".png\"\n";
+  file << "plot \\\n";
+  
+  std::list<column>::const_iterator it = cols.begin();
+  int count = 1;
+  while (it != cols.end())
+  {
+    file << '"' << op << ".dat\" using 0:" << count++ << " title \""
+         << it->libname << "\" with lines";
+    if (++it != cols.end())
+      file << ",\\\n";
+  }
+  file << std::endl;
+}
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_runner.hpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,80 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_TOOLS_BENCHMARK_RUNNER_HPP
+#define BOOST_MP_MATH_TOOLS_BENCHMARK_RUNNER_HPP
+
+#include <list>
+#include "benchmark.hpp"
+
+
+struct data_file
+{
+  struct column
+  {
+    std::string libname;
+    std::vector<double> data;
+    double total_ops;
+    bool operator < (const column& rhs) const { return libname < rhs.libname; }
+  };
+
+  std::string op;
+
+  std::list<column> cols;
+
+  void write() const;
+  void write_gnuplot_script(unsigned int x, unsigned int y) const;
+};
+
+
+struct benchmark_runner
+{
+  benchmark_runner(unsigned int num_input_samples,
+                   unsigned long operand_size_beg,
+                   unsigned long operand_size_end);
+
+  // add a library
+  void add_library(const boost::shared_ptr<benchmark_base>& b);
+  
+  // benches all operations given in ops
+  void run(const std::vector<std::string>& ops, double sample_time);
+
+  void write_data_files() const;
+  void write_gnuplot_scripts(unsigned int x, unsigned int y) const;
+  void write_summary_file() const;
+
+  void write_results(unsigned int x, unsigned int y) const;
+
+  void execute_bench_op(const std::string& op, double sample_time);
+
+private:
+
+  void init_libs();
+
+  void create_data_files();
+
+  void create_input_vectors(unsigned long min, unsigned long max);
+  void write_input_vector_plotfile(unsigned int x, unsigned int y) const;
+
+  unsigned long get_operand1_size(unsigned int) const;
+  unsigned long get_operand2_size(unsigned int) const;
+  
+  typedef std::vector<boost::shared_ptr<benchmark_base> > library_vec;
+  typedef std::list<benchmark_result>                     result_list;
+
+  const unsigned int num_input_samples_;
+  const unsigned long beg_;
+  const unsigned long end_;
+  std::vector<std::string> string_vec1_;
+  std::vector<std::string> string_vec2_;
+  library_vec libs_;
+  result_list results_;
+
+  std::list<data_file> dfiles_;
+};
+
+
+#endif
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,45 @@
+# Copyright Kevin Sopp 2008.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+alias boost_fs : $(BOOST_ROOT)/libs/filesystem/build//boost_filesystem/<link>shared ;
+alias boost_po : $(BOOST_ROOT)/libs/program_options/build//boost_program_options/<link>shared ;
+
+project
+  :
+    requirements
+    <include>../../../..
+    <include>.
+    <link>static
+    <toolset>gcc:<cxxflags>"-march=i686 -mtune=generic"
+  ;
+
+
+
+# GMP (GNU Multiple Precision Arithmetic, http://gmplib.org/) library need to be
+# installed for the benchmark to work
+# gmpxx is the library for the C++ bindings of gmp
+lib gmpxx : : <name>gmpxx ;
+lib gmp   : : <name>gmp ;
+
+lib tommath : tommath.cpp : <variant>release ;
+
+exe benchmark
+  :
+    benchmark.cpp
+    benchmark_runner.cpp
+    benchmark_mp_math.cpp
+    benchmark_libtom.cpp
+    benchmark_gmp.cpp
+    main.cpp
+    tommath
+    gmpxx gmp
+    boost_fs
+    boost_po
+  :
+    <variant>release
+    <toolset>gcc:<cxxflags>-std=c++0x #-DBOOST_MP_MATH_MP_INT_USE_ASM"
+  ;
+
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,325 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+#include <boost/tokenizer.hpp>
+
+#include "benchmark_runner.hpp"
+
+#include "benchmark_mp_math.hpp"
+#include "benchmark_libtom.hpp"
+#include "benchmark_gmp.hpp"
+
+
+const char* version = "0.3";
+
+
+struct config
+{
+  unsigned int graph_x, graph_y;
+  unsigned int num_input_samples;
+  double       max_error;
+  double       sample_time;
+  std::pair<unsigned int, unsigned int> range;
+
+  typedef std::vector<std::string> string_list;
+  // we receive these two strings from the cmdline and need to tokenize them
+  std::string ops_string;
+  std::string libs_string;
+  // the tokenized result
+  string_list ops;  // ops that we shall execute
+  string_list libs; // libs that we shall benchmark
+
+  config();
+
+  void show_available_ops (std::ostream&) const;
+
+  const string_list& available_ops () const { return available_ops_; }
+
+  double estimated_run_time() const;
+
+private:
+
+  string_list available_ops_;
+};
+
+
+config::config()
+{
+  available_ops_.push_back("ctor_dec");
+  available_ops_.push_back("ctor_hex");
+  available_ops_.push_back("to_dec");
+  available_ops_.push_back("to_hex");
+  available_ops_.push_back("add");
+  available_ops_.push_back("subtract");
+  available_ops_.push_back("multiply");
+  available_ops_.push_back("divide");
+  available_ops_.push_back("modulo");
+  available_ops_.push_back("square");
+  available_ops_.push_back("modpow");
+}
+
+
+
+void config::show_available_ops(std::ostream& os) const
+{
+  string_list::const_iterator op;
+  for (op = available_ops_.begin(); op != available_ops_.end(); ++op)
+    os << *op << "\n";
+}
+
+double config::estimated_run_time() const
+{
+  return sample_time * num_input_samples * ops.size() * libs.size();
+}
+
+
+double calibrate_sample_time(double max_error)
+{
+  const int vec_length = 10;
+  long vec[vec_length];
+  double st = 0.01;
+  
+  int verified = 0;
+  while (true)
+  {
+    for (int k = 0; k < vec_length; ++k)
+    {
+      boost::timer t;
+      boost::timer inner;
+      long count = 0;
+      while (inner.elapsed() < st)
+        ++count;
+      vec[k] = count;
+    }
+    // calculate error
+    long average_value = 0;
+    for (int i = 0; i < vec_length; ++i)
+      average_value += vec[i];
+    average_value /= vec_length;
+
+    long average_deviation = 0;
+    for (int i = 0; i < vec_length; ++i)
+      average_deviation += std::abs(average_value - vec[i]);
+    average_deviation /= vec_length;
+
+    const double error = (double)average_deviation / (double)average_value;
+    
+    std::cout << "sample-time = " << st
+              << ", current error = " << error;
+    if (verified)
+      std::cout << " (verifying)";
+    std::cout << std::endl;
+
+    if (error < max_error)
+    {
+      if (verified == 2)
+        return st;
+      ++verified;
+      continue;
+    }
+    else
+      verified = 0;
+    if (error / max_error > 2.0)
+      st += 0.01;
+    else
+      st += 0.002; 
+    if (st >= 0.05)
+      return 0.05;
+  }
+}
+
+
+
+
+int main(int argc, char** argv)
+{
+  typedef config::string_list string_list;
+  
+  std::ios::sync_with_stdio(false);
+
+  try
+  {
+
+  benchmark_manager bmgr;
+  bmgr.add(benchmark_ptr(new benchmark_mp_math()));
+  bmgr.add(benchmark_ptr(new benchmark_libtom()));
+  bmgr.add(benchmark_ptr(new benchmark_gmp()));
+
+  config c;
+
+  using namespace boost::program_options;
+
+  options_description opts
+    ("This program benchmarks different multiprecision integer "
+     "libraries and outputs data files for use with gnuplot "
+     "(http://www.gnuplot.com).\n"
+     "options"
+    );
+
+  opts.add_options()
+    ("help,h",    "show this message")
+
+    ("version,v", "print version")
+
+    ("num-input-samples,n",
+        value(&c.num_input_samples)->default_value(1000),
+          "number of input samples to create")
+   
+    ("max-error,e",
+        value(&c.max_error)->default_value(0.1, "0.1"),
+          "this value is used to calculate the sample time, you should not "
+          "need to modify it")
+    
+    ("sample-time,s",
+        value(&c.sample_time)->default_value(0.035, "0.035"),
+          "directly specify the sample time in seconds, it is used to reduce "
+          "the error of the measurements")
+    
+    ("range-beg,a",
+        value(&c.range.first)->default_value(32),
+          "range of numbers, measured in bits")
+    
+    ("range-end,b",
+        value(&c.range.second)->default_value(3072),
+          "range of numbers, measured in bits")
+    
+    ("ops", 
+        value(&c.ops_string),
+          "the operations to benchmark")
+    
+    ("libs",
+        value(&c.libs_string),
+          "the libraries to benchmark")
+    
+    ("list-ops",  "lists available operations")
+    
+    ("list-libs", "lists available libraries")
+
+    ("x",
+        value(&c.graph_x)->default_value(1024),
+          "width of graphs created by gnuplot")
+    ("y",
+        value(&c.graph_y)->default_value(768),
+          "height of graphs created by gnuplot")
+    ;
+
+  variables_map vm;
+
+  store(parse_command_line(argc, argv, opts), vm);
+
+  notify(vm);
+
+  if (vm.count("help"))
+  {
+    std::cout << opts << std::endl;
+    return 0;
+  }
+  if (vm.count("version"))
+  {
+    std::cout << version << std::endl;
+    return 0;
+  }
+  if (vm.count("list-ops"))
+  {
+    c.show_available_ops(std::cout);
+    return 0;
+  }
+  if (vm.count("list-libs"))
+  {
+    bmgr.print_available_libs(std::cout);
+    return 0;
+  }
+  if (!vm.count("ops"))
+    c.ops = c.available_ops();
+  else
+  {
+    boost::char_separator<char> sep(" ,");
+    boost::tokenizer<boost::char_separator<char> > tokens(c.ops_string, sep);
+    std::copy(tokens.begin(), tokens.end(), std::back_inserter(c.ops));
+  }
+
+  std::cout << "Ops that we are about to benchmark:\n";
+  for (string_list::const_iterator it = c.ops.begin(); it != c.ops.end(); ++it)
+    std::cout << "- " << *it << std::endl;
+
+  if (!vm.count("libs"))
+  {
+    for (benchmark_manager::b_set::const_iterator it = bmgr.b_.begin();
+        it != bmgr.b_.end(); ++it)
+    c.libs.push_back((*it)->name());
+  }
+  else
+  {
+    boost::char_separator<char> sep(" ,");
+    boost::tokenizer<boost::char_separator<char> > tokens(c.libs_string, sep);
+    std::copy(tokens.begin(), tokens.end(), std::back_inserter(c.libs));
+  }
+
+
+  // switch to a new subdir to store the benchmark results
+  const std::time_t time = std::time(0);
+  char timestring[32];
+  std::strftime(timestring, 32, "%Y %m %d %H:%M", std::localtime(&time));
+  
+  boost::filesystem::create_directory(timestring);
+  boost::filesystem::current_path(timestring);
+
+
+  benchmark_runner b_runner(c.num_input_samples, c.range.first, c.range.second);
+
+  std::cout << "Libraries that we are about to benchmark:\n";
+  for (string_list::const_iterator lib = c.libs.begin();
+       lib != c.libs.end(); ++lib)
+  {
+    const benchmark_ptr p(bmgr.get(*lib));
+    std::cout << "- " << p->name() << "\n";
+    b_runner.add_library(p);
+  }
+
+  if (!vm.count("sample-time"))
+  {
+    std::cout << "calibrating sample time..." << std::endl;
+    c.sample_time = calibrate_sample_time(c.max_error);
+  }
+    
+  std::cout << "Sample time is: " << c.sample_time << " sec" <<  std::endl;
+
+  const double runtime = c.estimated_run_time();
+  std::cout << "Estimated run time of benchmark is at least "
+            << (long)(runtime/60.0) << " minutes, but could be much longer for "
+            << "very large numbers." << std::endl;
+
+  b_runner.run(c.ops, c.sample_time);
+  b_runner.write_results(c.graph_x, c.graph_y);
+
+  std::cout << "done with benchmarking!" << std::endl;
+
+  std::cout << "creating graphs via gnuplot...\n";
+  std::cout << "calling \'gnuplot *.plt\'" << std::endl;
+  const int ret = std::system("gnuplot *.plt");
+  if (ret)
+    std::cout << "something went wrong, received the error code " << ret
+      << std::endl;
+  else
+    std::cout << "done" << std::endl;
+
+  if (boost::filesystem::is_empty(boost::filesystem::current_path()))
+    boost::filesystem::remove(boost::filesystem::current_path());
+
+  }
+  catch (const std::exception& e)
+  {
+    std::cerr << "caught exception: " << e.what() << std::endl;
+    return 1;
+  }
+
+  return 0;
+}
+
+
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/tommath.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/tommath.cpp	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,9524 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* Start: bn_error.c */
+#include "tommath.h"
+#ifdef BN_ERROR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+static const struct {
+     int code;
+     const char *msg;
+} msgs[] = {
+     { MP_OKAY, "Successful" },
+     { MP_MEM,  "Out of heap" },
+     { MP_VAL,  "Value out of range" }
+};
+
+/* return a char * string for a given code */
+const char *mp_error_to_string(int code)
+{
+   int x;
+
+   /* scan the lookup table for the given message */
+   for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
+       if (msgs[x].code == code) {
+          return msgs[x].msg;
+       }
+   }
+
+   /* generic reply for invalid code */
+   return "Invalid error code";
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_error.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_error.c */
+
+/* Start: bn_fast_mp_invmod.c */
+#include "tommath.h"
+#ifdef BN_FAST_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes the modular inverse via binary extended euclidean algorithm, 
+ * that is c = 1/a mod b 
+ *
+ * Based on slow invmod except this is optimized for the case where b is 
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, B, D;
+  int     res, neg;
+
+  /* 2. [modified] b must be odd   */
+  if (mp_iseven (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init all our temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x == modulus, y == value to invert */
+  if ((res = mp_copy (b, &x)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* we need y = |a| */
+  if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if B is odd then */
+    if (mp_isodd (&B) == 1) {
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* B = B/2 */
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if D is odd then */
+    if (mp_isodd (&D) == 1) {
+      /* D = (D-x)/2 */
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* D = D/2 */
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0) {
+    goto top;
+  }
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* b is now the inverse */
+  neg = a->sign;
+  while (D.sign == MP_NEG) {
+    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+  mp_exch (&D, c);
+  c->sign = neg;
+  res = MP_OKAY;
+
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_mp_invmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_fast_mp_invmod.c */
+
+/* Start: bn_fast_mp_montgomery_reduce.c */
+#include "tommath.h"
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+  mp_word W[MP_WARRAY];
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    register mp_word *_W;
+    register mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    register mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      register int iy;
+      register mp_digit *tmpn;
+      register mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    register mp_digit *tmpx;
+    register mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero oldused digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_fast_mp_montgomery_reduce.c */
+
+/* Start: bn_fast_s_mp_mul_digs.c */
+#include "tommath.h"
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier.  It is 
+ * designed to compute the columns of the product first 
+ * then handle the carries afterwards.  This has the effect 
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of 
+ * digits of output so if say only a half-product is required 
+ * you don't have to compute the upper half (a feature 
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  register mp_word  _W;
+
+  /* grow the destination as required */
+  if (c->alloc < digs) {
+    if ((res = mp_grow (c, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = MIN(digs, a->used + b->used);
+
+  /* clear the carry */
+  _W = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty;
+      int      iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially 
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; ++iz) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+      }
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+    tmpc = c->dp;
+    for (ix = 0; ix < pa+1; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_digs.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_fast_s_mp_mul_digs.c */
+
+/* Start: bn_fast_s_mp_mul_high_digs.c */
+#include "tommath.h"
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs.  See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed.  This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  mp_word  _W;
+
+  /* grow the destination as required */
+  pa = a->used + b->used;
+  if (c->alloc < pa) {
+    if ((res = mp_grow (c, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = a->used + b->used;
+  _W = 0;
+  for (ix = digs; ix < pa; ix++) { 
+      int      tx, ty, iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially its 
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+  }
+  
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+
+    tmpc = c->dp + digs;
+    for (ix = digs; ix < pa; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_fast_s_mp_mul_high_digs.c */
+
+/* Start: bn_fast_s_mp_sqr.c */
+#include "tommath.h"
+#ifdef BN_FAST_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that 
+ * starts closer to zero] can't equal the offset of tmpy.  
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens.  You double all those 
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int       olduse, res, pa, ix, iz;
+  mp_digit   W[MP_WARRAY], *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty 
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = (mp_digit)(_W & MP_MASK);
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = a->used+a->used;
+
+  {
+    mp_digit *tmpb;
+    tmpb = b->dp;
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = W[ix] & MP_MASK;
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_fast_s_mp_sqr.c */
+
+/* Start: bn_mp_2expt.c */
+#include "tommath.h"
+#ifdef BN_MP_2EXPT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes a = 2**b 
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+  int     res;
+
+  /* zero a as per default */
+  mp_zero (a);
+
+  /* grow a to accomodate the single bit */
+  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set the used count of where the bit will go */
+  a->used = b / DIGIT_BIT + 1;
+
+  /* put the single bit in its place */
+  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_2expt.c */
+
+/* Start: bn_mp_abs.c */
+#include "tommath.h"
+#ifdef BN_MP_ABS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* b = |a| 
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_abs.c */
+
+/* Start: bn_mp_add.c */
+#include "tommath.h"
+#ifdef BN_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_add.c */
+
+/* Start: bn_mp_add_d.c */
+#include "tommath.h"
+#ifdef BN_MP_ADD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* single digit addition */
+int
+mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  int     res, ix, oldused;
+  mp_digit *tmpa, *tmpc, mu;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative and |a| >= b, call c = |a| - b */
+  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+     /* temporarily fix sign of a */
+     a->sign = MP_ZPOS;
+
+     /* c = |a| - b */
+     res = mp_sub_d(a, b, c);
+
+     /* fix sign  */
+     a->sign = c->sign = MP_NEG;
+
+     /* clamp */
+     mp_clamp(c);
+
+     return res;
+  }
+
+  /* old number of used digits in c */
+  oldused = c->used;
+
+  /* sign always positive */
+  c->sign = MP_ZPOS;
+
+  /* source alias */
+  tmpa    = a->dp;
+
+  /* destination alias */
+  tmpc    = c->dp;
+
+  /* if a is positive */
+  if (a->sign == MP_ZPOS) {
+     /* add digit, after this we're propagating
+      * the carry.
+      */
+     *tmpc   = *tmpa++ + b;
+     mu      = *tmpc >> DIGIT_BIT;
+     *tmpc++ &= MP_MASK;
+
+     /* now handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc   = *tmpa++ + mu;
+        mu      = *tmpc >> DIGIT_BIT;
+        *tmpc++ &= MP_MASK;
+     }
+     /* set final carry */
+     ix++;
+     *tmpc++  = mu;
+
+     /* setup size */
+     c->used = a->used + 1;
+  } else {
+     /* a was negative and |a| < b */
+     c->used  = 1;
+
+     /* the result is a single digit */
+     if (a->used == 1) {
+        *tmpc++  =  b - a->dp[0];
+     } else {
+        *tmpc++  =  b;
+     }
+
+     /* setup count so the clearing of oldused
+      * can fall through correctly
+      */
+     ix       = 1;
+  }
+
+  /* now zero to oldused */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_add_d.c */
+
+/* Start: bn_mp_addmod.c */
+#include "tommath.h"
+#ifdef BN_MP_ADDMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* d = a + b (mod c) */
+int
+mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_add (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_addmod.c */
+
+/* Start: bn_mp_and.c */
+#include "tommath.h"
+#ifdef BN_MP_AND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* AND two ints together */
+int
+mp_and (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] &= x->dp[ix];
+  }
+
+  /* zero digits above the last from the smallest mp_int */
+  for (; ix < t.used; ix++) {
+    t.dp[ix] = 0;
+  }
+
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_and.c */
+
+/* Start: bn_mp_clamp.c */
+#include "tommath.h"
+#ifdef BN_MP_CLAMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* trim unused digits 
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_clamp.c */
+
+/* Start: bn_mp_clear.c */
+#include "tommath.h"
+#ifdef BN_MP_CLEAR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* clear one (frees)  */
+void
+mp_clear (mp_int * a)
+{
+  int i;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    XFREE(a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_clear.c */
+
+/* Start: bn_mp_clear_multi.c */
+#include "tommath.h"
+#ifdef BN_MP_CLEAR_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+#include <stdarg.h>
+
+void mp_clear_multi(mp_int *mp, ...) 
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_clear_multi.c */
+
+/* Start: bn_mp_cmp.c */
+#include "tommath.h"
+#ifdef BN_MP_CMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+  
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_cmp.c */
+
+/* Start: bn_mp_cmp_d.c */
+#include "tommath.h"
+#ifdef BN_MP_CMP_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* compare based on sign */
+  if (a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_cmp_d.c */
+
+/* Start: bn_mp_cmp_mag.c */
+#include "tommath.h"
+#ifdef BN_MP_CMP_MAG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+  
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_cmp_mag.c */
+
+/* Start: bn_mp_cnt_lsb.c */
+#include "tommath.h"
+#ifdef BN_MP_CNT_LSB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+static const int lnz[16] = { 
+   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+   int x;
+   mp_digit q, qq;
+
+   /* easy out */
+   if (mp_iszero(a) == 1) {
+      return 0;
+   }
+
+   /* scan lower digits until non-zero */
+   for (x = 0; x < a->used && a->dp[x] == 0; x++);
+   q = a->dp[x];
+   x *= DIGIT_BIT;
+
+   /* now scan this digit until a 1 is found */
+   if ((q & 1) == 0) {
+      do {
+         qq  = q & 15;
+         x  += lnz[qq];
+         q >>= 4;
+      } while (qq == 0);
+   }
+   return x;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_cnt_lsb.c */
+
+/* Start: bn_mp_copy.c */
+#include "tommath.h"
+#ifdef BN_MP_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    register mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_copy.c */
+
+/* Start: bn_mp_count_bits.c */
+#include "tommath.h"
+#ifdef BN_MP_COUNT_BITS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+  
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_count_bits.c */
+
+/* Start: bn_mp_div.c */
+#include "tommath.h"
+#ifdef BN_MP_DIV_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+	
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+     return res;
+  }
+
+
+  mp_set(&tq, 1);
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+      ((res = mp_abs(b, &tb)) != MP_OKAY) || 
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto LBL_ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto LBL_ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto LBL_ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+  }
+LBL_ERR:
+   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+   return res;
+}
+
+#else
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto LBL_Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto LBL_X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto LBL_Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
+             xi * b**2 + xi-1 * b + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+  return res;
+}
+
+#endif
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_div.c */
+
+/* Start: bn_mp_div_2.c */
+#include "tommath.h"
+#ifdef BN_MP_DIV_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_div_2.c */
+
+/* Start: bn_mp_div_2d.c */
+#include "tommath.h"
+#ifdef BN_MP_DIV_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_div_2d.c */
+
+/* Start: bn_mp_div_3.c */
+#include "tommath.h"
+#ifdef BN_MP_DIV_3_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+  mp_int   q;
+  mp_word  w, t;
+  mp_digit b;
+  int      res, ix;
+  
+  /* b = 2**DIGIT_BIT / 3 */
+  b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+     if (w >= 3) {
+        /* multiply w by [1/3] */
+        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+        /* now subtract 3 * [w/3] from w, to get the remainder */
+        w -= t+t+t;
+
+        /* fixup the remainder as required since
+         * the optimization is not exact.
+         */
+        while (w >= 3) {
+           t += 1;
+           w -= 3;
+        }
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+
+  /* [optional] store the remainder */
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+
+  /* [optional] store the quotient */
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_div_3.c */
+
+/* Start: bn_mp_div_d.c */
+#include "tommath.h"
+#ifdef BN_MP_DIV_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+   int x;
+
+   /* fast return if no power of two */
+   if ((b==0) || (b & (b-1))) {
+      return 0;
+   }
+
+   for (x = 0; x < DIGIT_BIT; x++) {
+      if (b == (((mp_digit)1)<<x)) {
+         *p = x;
+         return 1;
+      }
+   }
+   return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+  mp_int  q;
+  mp_word w;
+  mp_digit t;
+  int     res, ix;
+
+  /* cannot divide by zero */
+  if (b == 0) {
+     return MP_VAL;
+  }
+
+  /* quick outs */
+  if (b == 1 || mp_iszero(a) == 1) {
+     if (d != NULL) {
+        *d = 0;
+     }
+     if (c != NULL) {
+        return mp_copy(a, c);
+     }
+     return MP_OKAY;
+  }
+
+  /* power of two ? */
+  if (s_is_power_of_two(b, &ix) == 1) {
+     if (d != NULL) {
+        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+     }
+     if (c != NULL) {
+        return mp_div_2d(a, ix, c, NULL);
+     }
+     return MP_OKAY;
+  }
+
+#ifdef BN_MP_DIV_3_C
+  /* three? */
+  if (b == 3) {
+     return mp_div_3(a, c, d);
+  }
+#endif
+
+  /* no easy answer [c'est la vie].  Just division */
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+     
+     if (w >= b) {
+        t = (mp_digit)(w / b);
+        w -= ((mp_word)t) * ((mp_word)b);
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+  
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+  
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2007/01/09 04:44:32 $ */
+
+/* End: bn_mp_div_d.c */
+
+/* Start: bn_mp_dr_is_modulus.c */
+#include "tommath.h"
+#ifdef BN_MP_DR_IS_MODULUS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+   int ix;
+
+   /* must be at least two digits */
+   if (a->used < 2) {
+      return 0;
+   }
+
+   /* must be of the form b**k - a [a <= b] so all
+    * but the first digit must be equal to -1 (mod b).
+    */
+   for (ix = 1; ix < a->used; ix++) {
+       if (a->dp[ix] != MP_MASK) {
+          return 0;
+       }
+   }
+   return 1;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_dr_is_modulus.c */
+
+/* Start: bn_mp_dr_reduce.c */
+#include "tommath.h"
+#ifdef BN_MP_DR_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ *                 Chae Hoon Lim, Pil Joong Lee,
+ *          POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+  int      err, i, m;
+  mp_word  r;
+  mp_digit mu, *tmpx1, *tmpx2;
+
+  /* m = digits in modulus */
+  m = n->used;
+
+  /* ensure that "x" has at least 2m digits */
+  if (x->alloc < m + m) {
+    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+      return err;
+    }
+  }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+  /* aliases for digits */
+  /* alias for lower half of x */
+  tmpx1 = x->dp;
+
+  /* alias for upper half of x, or x/B**m */
+  tmpx2 = x->dp + m;
+
+  /* set carry to zero */
+  mu = 0;
+
+  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+  for (i = 0; i < m; i++) {
+      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+      *tmpx1++  = (mp_digit)(r & MP_MASK);
+      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+  }
+
+  /* set final carry */
+  *tmpx1++ = mu;
+
+  /* zero words above m */
+  for (i = m + 1; i < x->used; i++) {
+      *tmpx1++ = 0;
+  }
+
+  /* clamp, sub and return */
+  mp_clamp (x);
+
+  /* if x >= n then subtract and reduce again
+   * Each successive "recursion" makes the input smaller and smaller.
+   */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    s_mp_sub(x, n, x);
+    goto top;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_dr_reduce.c */
+
+/* Start: bn_mp_dr_setup.c */
+#include "tommath.h"
+#ifdef BN_MP_DR_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+   /* the casts are required if DIGIT_BIT is one less than
+    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+    */
+   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
+        ((mp_word)a->dp[0]));
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_dr_setup.c */
+
+/* Start: bn_mp_exch.c */
+#include "tommath.h"
+#ifdef BN_MP_EXCH_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* swap the elements of two integers, for cases where you can't simply swap the 
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_exch.c */
+
+/* Start: bn_mp_expt_d.c */
+#include "tommath.h"
+#ifdef BN_MP_EXPT_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* calculate c = a**b  using a square-multiply algorithm */
+int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  int     res, x;
+  mp_int  g;
+
+  if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set initial result */
+  mp_set (c, 1);
+
+  for (x = 0; x < (int) DIGIT_BIT; x++) {
+    /* square */
+    if ((res = mp_sqr (c, c)) != MP_OKAY) {
+      mp_clear (&g);
+      return res;
+    }
+
+    /* if the bit is set multiply */
+    if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
+      if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
+         mp_clear (&g);
+         return res;
+      }
+    }
+
+    /* shift to next bit */
+    b <<= 1;
+  }
+
+  mp_clear (&g);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_expt_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_expt_d.c */
+
+/* Start: bn_mp_exptmod.c */
+#include "tommath.h"
+#ifdef BN_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear_multi(&tmpG, &tmpX, NULL);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear_multi(&tmpG, &tmpX, NULL);
+     return err;
+#else 
+     /* no invmod */
+     return MP_VAL;
+#endif
+  }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+  if (mp_reduce_is_2k_l(P) == MP_YES) {
+     return s_mp_exptmod(G, X, P, Y, 1);
+  }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+#else
+  /* default to no */
+  dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+  /* if not, is it a unrestricted DR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+#endif
+    
+  /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+  if (mp_isodd (P) == 1 || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y, 0);
+#else
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_exptmod.c */
+
+/* Start: bn_mp_exptmod_fast.c */
+#include "tommath.h"
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C     
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+
+     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+     if (((P->used * 2 + 1) < MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else 
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+#else
+        err = MP_VAL;
+        goto LBL_M;
+#endif
+     }
+  } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+     redux = mp_reduce_2k;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  /* create M table
+   *
+
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+#else 
+     err = MP_VAL;
+     goto LBL_RES;
+#endif
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  } else {
+     mp_set(&res, 1);
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto LBL_RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod_fast.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_exptmod_fast.c */
+
+/* Start: bn_mp_exteuclid.c */
+#include "tommath.h"
+#ifdef BN_MP_EXTEUCLID_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* Extended euclidean algorithm of (a, b) produces 
+   a*u1 + b*u2 = u3
+ */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
+{
+   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
+   int err;
+
+   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
+      return err;
+   }
+
+   /* initialize, (u1,u2,u3) = (1,0,a) */
+   mp_set(&u1, 1);
+   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* initialize, (v1,v2,v3) = (0,1,b) */
+   mp_set(&v2, 1);
+   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* loop while v3 != 0 */
+   while (mp_iszero(&v3) == MP_NO) {
+       /* q = u3/v3 */
+       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }
+
+       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
+       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }
+
+       /* (u1,u2,u3) = (v1,v2,v3) */
+       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }
+
+       /* (v1,v2,v3) = (t1,t2,t3) */
+       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
+   }
+
+   /* make sure U3 >= 0 */
+   if (u3.sign == MP_NEG) {
+      mp_neg(&u1, &u1);
+      mp_neg(&u2, &u2);
+      mp_neg(&u3, &u3);
+   }
+
+   /* copy result out */
+   if (U1 != NULL) { mp_exch(U1, &u1); }
+   if (U2 != NULL) { mp_exch(U2, &u2); }
+   if (U3 != NULL) { mp_exch(U3, &u3); }
+
+   err = MP_OKAY;
+_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+   return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_exteuclid.c */
+
+/* Start: bn_mp_fread.c */
+#include "tommath.h"
+#ifdef BN_MP_FREAD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* read a bigint from a file stream in ASCII */
+int mp_fread(mp_int *a, int radix, FILE *stream)
+{
+   int err, ch, neg, y;
+   
+   /* clear a */
+   mp_zero(a);
+   
+   /* if first digit is - then set negative */
+   ch = fgetc(stream);
+   if (ch == '-') {
+      neg = MP_NEG;
+      ch = fgetc(stream);
+   } else {
+      neg = MP_ZPOS;
+   }
+   
+   for (;;) {
+      /* find y in the radix map */
+      for (y = 0; y < radix; y++) {
+          if (mp_s_rmap[y] == ch) {
+             break;
+          }
+      }
+      if (y == radix) {
+         break;
+      }
+      
+      /* shift up and add */
+      if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+         return err;
+      }
+      if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+         return err;
+      }
+      
+      ch = fgetc(stream);
+   }
+   if (mp_cmp_d(a, 0) != MP_EQ) {
+      a->sign = neg;
+   }
+   
+   return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_fread.c */
+
+/* Start: bn_mp_fwrite.c */
+#include "tommath.h"
+#ifdef BN_MP_FWRITE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+int mp_fwrite(mp_int *a, int radix, FILE *stream)
+{
+   char *buf;
+   int err, len, x;
+   
+   if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
+      return err;
+   }
+
+   buf = OPT_CAST(char) XMALLOC (len);
+   if (buf == NULL) {
+      return MP_MEM;
+   }
+   
+   if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
+      XFREE (buf);
+      return err;
+   }
+   
+   for (x = 0; x < len; x++) {
+       if (fputc(buf[x], stream) == EOF) {
+          XFREE (buf);
+          return MP_VAL;
+       }
+   }
+   
+   XFREE (buf);
+   return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_fwrite.c */
+
+/* Start: bn_mp_gcd.c */
+#include "tommath.h"
+#ifdef BN_MP_GCD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  u, v;
+  int     k, u_lsb, v_lsb, res;
+
+  /* either zero than gcd is the largest */
+  if (mp_iszero (a) == MP_YES) {
+    return mp_abs (b, c);
+  }
+  if (mp_iszero (b) == MP_YES) {
+    return mp_abs (a, c);
+  }
+
+  /* get copies of a and b we can modify */
+  if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+    goto LBL_U;
+  }
+
+  /* must be positive for the remainder of the algorithm */
+  u.sign = v.sign = MP_ZPOS;
+
+  /* B1.  Find the common power of two for u and v */
+  u_lsb = mp_cnt_lsb(&u);
+  v_lsb = mp_cnt_lsb(&v);
+  k     = MIN(u_lsb, v_lsb);
+
+  if (k > 0) {
+     /* divide the power of two out */
+     if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+
+     if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  /* divide any remaining factors of two out */
+  if (u_lsb != k) {
+     if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  if (v_lsb != k) {
+     if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  while (mp_iszero(&v) == 0) {
+     /* make sure v is the largest */
+     if (mp_cmp_mag(&u, &v) == MP_GT) {
+        /* swap u and v to make sure v is >= u */
+        mp_exch(&u, &v);
+     }
+     
+     /* subtract smallest from largest */
+     if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+        goto LBL_V;
+     }
+     
+     /* Divide out all factors of two */
+     if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     } 
+  } 
+
+  /* multiply by 2**k which we divided out at the beginning */
+  if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+     goto LBL_V;
+  }
+  c->sign = MP_ZPOS;
+  res = MP_OKAY;
+LBL_V:mp_clear (&u);
+LBL_U:mp_clear (&v);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_gcd.c */
+
+/* Start: bn_mp_get_int.c */
+#include "tommath.h"
+#ifdef BN_MP_GET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* get the lower 32-bits of an mp_int */
+unsigned long mp_get_int(mp_int * a) 
+{
+  int i;
+  unsigned long res;
+
+  if (a->used == 0) {
+     return 0;
+  }
+
+  /* get number of digits of the lsb we have to read */
+  i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
+
+  /* get most significant digit of result */
+  res = DIGIT(a,i);
+   
+  while (--i >= 0) {
+    res = (res << DIGIT_BIT) | DIGIT(a,i);
+  }
+
+  /* force result to 32-bits always so it is consistent on non 32-bit platforms */
+  return res & 0xFFFFFFFFUL;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_get_int.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_get_int.c */
+
+/* Start: bn_mp_grow.c */
+#include "tommath.h"
+#ifdef BN_MP_GROW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_grow.c */
+
+/* Start: bn_mp_init.c */
+#include "tommath.h"
+#ifdef BN_MP_INIT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+  int i;
+
+  /* allocate memory required and clear it */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_init.c */
+
+/* Start: bn_mp_init_copy.c */
+#include "tommath.h"
+#ifdef BN_MP_INIT_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init (a)) != MP_OKAY) {
+    return res;
+  }
+  return mp_copy (b, a);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_init_copy.c */
+
+/* Start: bn_mp_init_multi.c */
+#include "tommath.h"
+#ifdef BN_MP_INIT_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+#include <stdarg.h>
+
+int mp_init_multi(mp_int *mp, ...) 
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+            
+            /* end the current list */
+            va_end(args);
+            
+            /* now start cleaning up */            
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_init_multi.c */
+
+/* Start: bn_mp_init_set.c */
+#include "tommath.h"
+#ifdef BN_MP_INIT_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b)
+{
+  int err;
+  if ((err = mp_init(a)) != MP_OKAY) {
+     return err;
+  }
+  mp_set(a, b);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_init_set.c */
+
+/* Start: bn_mp_init_set_int.c */
+#include "tommath.h"
+#ifdef BN_MP_INIT_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* initialize and set a digit */
+int mp_init_set_int (mp_int * a, unsigned long b)
+{
+  int err;
+  if ((err = mp_init(a)) != MP_OKAY) {
+     return err;
+  }
+  return mp_set_int(a, b);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_set_int.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_init_set_int.c */
+
+/* Start: bn_mp_init_size.c */
+#include "tommath.h"
+#ifdef BN_MP_INIT_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);	
+  
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_init_size.c */
+
+/* Start: bn_mp_invmod.c */
+#include "tommath.h"
+#ifdef BN_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#endif
+
+  return MP_VAL;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_invmod.c */
+
+/* Start: bn_mp_invmod_slow.c */
+#include "tommath.h"
+#ifdef BN_MP_INVMOD_SLOW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, A, B, C, D;
+  int     res;
+
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, 
+                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x = a, y = b */
+  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+      goto LBL_ERR;
+  }
+  if ((res = mp_copy (b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 2. [modified] if x,y are both even then return an error! */
+  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  mp_set (&A, 1);
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if A or B is odd then */
+    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* A = A/2, B = B/2 */
+    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if C or D is odd then */
+    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* C = C/2, D = D/2 */
+    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, A = A - C, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, C = C - A, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0)
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* if its too low */
+  while (mp_cmp_d(&C, 0) == MP_LT) {
+      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* too big */
+  while (mp_cmp_mag(&C, b) != MP_LT) {
+      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* C is now the inverse */
+  mp_exch (&C, c);
+  res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_invmod_slow.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_invmod_slow.c */
+
+/* Start: bn_mp_is_square.c */
+#include "tommath.h"
+#ifdef BN_MP_IS_SQUARE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* Check if remainders are possible squares - fast exclude non-squares */
+static const char rem_128[128] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char rem_105[105] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+};
+
+/* Store non-zero to ret if arg is square, and zero if not */
+int mp_is_square(mp_int *arg,int *ret) 
+{
+  int           res;
+  mp_digit      c;
+  mp_int        t;
+  unsigned long r;
+
+  /* Default to Non-square :) */
+  *ret = MP_NO; 
+
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* digits used?  (TSD) */
+  if (arg->used == 0) {
+     return MP_OKAY;
+  }
+
+  /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
+  if (rem_128[127 & DIGIT(arg,0)] == 1) {
+     return MP_OKAY;
+  }
+
+  /* Next check mod 105 (3*5*7) */
+  if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
+     return res;
+  }
+  if (rem_105[c] == 1) {
+     return MP_OKAY;
+  }
+
+
+  if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
+     return res;
+  }
+  if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  r = mp_get_int(&t);
+  /* Check for other prime modules, note it's not an ERROR but we must
+   * free "t" so the easiest way is to goto ERR.  We know that res
+   * is already equal to MP_OKAY from the mp_mod call 
+   */ 
+  if ( (1L<<(r%11)) & 0x5C4L )             goto ERR;
+  if ( (1L<<(r%13)) & 0x9E4L )             goto ERR;
+  if ( (1L<<(r%17)) & 0x5CE8L )            goto ERR;
+  if ( (1L<<(r%19)) & 0x4F50CL )           goto ERR;
+  if ( (1L<<(r%23)) & 0x7ACCA0L )          goto ERR;
+  if ( (1L<<(r%29)) & 0xC2EDD0CL )         goto ERR;
+  if ( (1L<<(r%31)) & 0x6DE2B848L )        goto ERR;
+
+  /* Final check - is sqr(sqrt(arg)) == arg ? */
+  if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+
+  *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
+ERR:mp_clear(&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_is_square.c */
+
+/* Start: bn_mp_jacobi.c */
+#include "tommath.h"
+#ifdef BN_MP_JACOBI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes the jacobi c = (a | n) (or Legendre if n is prime)
+ * HAC pp. 73 Algorithm 2.149
+ */
+int mp_jacobi (mp_int * a, mp_int * p, int *c)
+{
+  mp_int  a1, p1;
+  int     k, s, r, res;
+  mp_digit residue;
+
+  /* if p <= 0 return MP_VAL */
+  if (mp_cmp_d(p, 0) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* step 1.  if a == 0, return 0 */
+  if (mp_iszero (a) == 1) {
+    *c = 0;
+    return MP_OKAY;
+  }
+
+  /* step 2.  if a == 1, return 1 */
+  if (mp_cmp_d (a, 1) == MP_EQ) {
+    *c = 1;
+    return MP_OKAY;
+  }
+
+  /* default */
+  s = 0;
+
+  /* step 3.  write a = a1 * 2**k  */
+  if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init (&p1)) != MP_OKAY) {
+    goto LBL_A1;
+  }
+
+  /* divide out larger power of two */
+  k = mp_cnt_lsb(&a1);
+  if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
+     goto LBL_P1;
+  }
+
+  /* step 4.  if e is even set s=1 */
+  if ((k & 1) == 0) {
+    s = 1;
+  } else {
+    /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
+    residue = p->dp[0] & 7;
+
+    if (residue == 1 || residue == 7) {
+      s = 1;
+    } else if (residue == 3 || residue == 5) {
+      s = -1;
+    }
+  }
+
+  /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+  if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
+    s = -s;
+  }
+
+  /* if a1 == 1 we're done */
+  if (mp_cmp_d (&a1, 1) == MP_EQ) {
+    *c = s;
+  } else {
+    /* n1 = n mod a1 */
+    if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
+      goto LBL_P1;
+    }
+    if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
+      goto LBL_P1;
+    }
+    *c = s * r;
+  }
+
+  /* done */
+  res = MP_OKAY;
+LBL_P1:mp_clear (&p1);
+LBL_A1:mp_clear (&a1);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_jacobi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_jacobi.c */
+
+/* Start: bn_mp_karatsuba_mul.c */
+#include "tommath.h"
+#ifdef BN_MP_KARATSUBA_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* c = |a| * |b| using Karatsuba Multiplication using 
+ * three half size multiplications
+ *
+ * Let B represent the radix [e.g. 2**DIGIT_BIT] and 
+ * let n represent half of the number of digits in 
+ * the min(a,b)
+ *
+ * a = a1 * B**n + a0
+ * b = b1 * B**n + b0
+ *
+ * Then, a * b => 
+   a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
+ *
+ * Note that a1b1 and a0b0 are used twice and only need to be 
+ * computed once.  So in total three half size (half # of 
+ * digit) multiplications are performed, a0b0, a1b1 and 
+ * (a1+b1)(a0+b0)
+ *
+ * Note that a multiplication of half the digits requires
+ * 1/4th the number of single precision multiplications so in 
+ * total after one call 25% of the single precision multiplications 
+ * are saved.  Note also that the call to mp_mul can end up back 
+ * in this function if the a0, a1, b0, or b1 are above the threshold.  
+ * This is known as divide-and-conquer and leads to the famous 
+ * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 
+ * the standard O(N**2) that the baseline/comba methods use.  
+ * Generally though the overhead of this method doesn't pay off 
+ * until a certain size (N ~ 80) is reached.
+ */
+int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x0, x1, y0, y1, t1, x0y0, x1y1;
+  int     B, err;
+
+  /* default the return code to an error */
+  err = MP_MEM;
+
+  /* min # of digits */
+  B = MIN (a->used, b->used);
+
+  /* now divide in two */
+  B = B >> 1;
+
+  /* init copy all the temps */
+  if (mp_init_size (&x0, B) != MP_OKAY)
+    goto ERR;
+  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+    goto X0;
+  if (mp_init_size (&y0, B) != MP_OKAY)
+    goto X1;
+  if (mp_init_size (&y1, b->used - B) != MP_OKAY)
+    goto Y0;
+
+  /* init temps */
+  if (mp_init_size (&t1, B * 2) != MP_OKAY)
+    goto Y1;
+  if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
+    goto T1;
+  if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
+    goto X0Y0;
+
+  /* now shift the digits */
+  x0.used = y0.used = B;
+  x1.used = a->used - B;
+  y1.used = b->used - B;
+
+  {
+    register int x;
+    register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
+
+    /* we copy the digits directly instead of using higher level functions
+     * since we also need to shift the digits
+     */
+    tmpa = a->dp;
+    tmpb = b->dp;
+
+    tmpx = x0.dp;
+    tmpy = y0.dp;
+    for (x = 0; x < B; x++) {
+      *tmpx++ = *tmpa++;
+      *tmpy++ = *tmpb++;
+    }
+
+    tmpx = x1.dp;
+    for (x = B; x < a->used; x++) {
+      *tmpx++ = *tmpa++;
+    }
+
+    tmpy = y1.dp;
+    for (x = B; x < b->used; x++) {
+      *tmpy++ = *tmpb++;
+    }
+  }
+
+  /* only need to clamp the lower words since by definition the 
+   * upper words x1/y1 must have a known number of digits
+   */
+  mp_clamp (&x0);
+  mp_clamp (&y0);
+
+  /* now calc the products x0y0 and x1y1 */
+  /* after this x0 is no longer required, free temp [x0==t2]! */
+  if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)  
+    goto X1Y1;          /* x0y0 = x0*y0 */
+  if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
+    goto X1Y1;          /* x1y1 = x1*y1 */
+
+  /* now calc x1+x0 and y1+y0 */
+  if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x1 - x0 */
+  if (s_mp_add (&y1, &y0, &x0) != MP_OKAY)
+    goto X1Y1;          /* t2 = y1 - y0 */
+  if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = (x1 + x0) * (y1 + y0) */
+
+  /* add x0y0 */
+  if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
+    goto X1Y1;          /* t2 = x0y0 + x1y1 */
+  if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
+
+  /* shift by B */
+  if (mp_lshd (&t1, B) != MP_OKAY)
+    goto X1Y1;          /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+  if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+    goto X1Y1;          /* x1y1 = x1y1 << 2*B */
+
+  if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 */
+  if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 + x1y1 */
+
+  /* Algorithm succeeded set the return code to MP_OKAY */
+  err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_mul.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_karatsuba_mul.c */
+
+/* Start: bn_mp_karatsuba_sqr.c */
+#include "tommath.h"
+#ifdef BN_MP_KARATSUBA_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* Karatsuba squaring, computes b = a*a using three 
+ * half size squarings
+ *
+ * See comments of karatsuba_mul for details.  It 
+ * is essentially the same algorithm but merely 
+ * tuned to perform recursive squarings.
+ */
+int mp_karatsuba_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  x0, x1, t1, t2, x0x0, x1x1;
+  int     B, err;
+
+  err = MP_MEM;
+
+  /* min # of digits */
+  B = a->used;
+
+  /* now divide in two */
+  B = B >> 1;
+
+  /* init copy all the temps */
+  if (mp_init_size (&x0, B) != MP_OKAY)
+    goto ERR;
+  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+    goto X0;
+
+  /* init temps */
+  if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
+    goto X1;
+  if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
+    goto T1;
+  if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
+    goto T2;
+  if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
+    goto X0X0;
+
+  {
+    register int x;
+    register mp_digit *dst, *src;
+
+    src = a->dp;
+
+    /* now shift the digits */
+    dst = x0.dp;
+    for (x = 0; x < B; x++) {
+      *dst++ = *src++;
+    }
+
+    dst = x1.dp;
+    for (x = B; x < a->used; x++) {
+      *dst++ = *src++;
+    }
+  }
+
+  x0.used = B;
+  x1.used = a->used - B;
+
+  mp_clamp (&x0);
+
+  /* now calc the products x0*x0 and x1*x1 */
+  if (mp_sqr (&x0, &x0x0) != MP_OKAY)
+    goto X1X1;           /* x0x0 = x0*x0 */
+  if (mp_sqr (&x1, &x1x1) != MP_OKAY)
+    goto X1X1;           /* x1x1 = x1*x1 */
+
+  /* now calc (x1+x0)**2 */
+  if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x1 - x0 */
+  if (mp_sqr (&t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = (x1 - x0) * (x1 - x0) */
+
+  /* add x0y0 */
+  if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
+    goto X1X1;           /* t2 = x0x0 + x1x1 */
+  if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
+
+  /* shift by B */
+  if (mp_lshd (&t1, B) != MP_OKAY)
+    goto X1X1;           /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
+  if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+    goto X1X1;           /* x1x1 = x1x1 << 2*B */
+
+  if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 */
+  if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 + x1x1 */
+
+  err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_sqr.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_karatsuba_sqr.c */
+
+/* Start: bn_mp_lcm.c */
+#include "tommath.h"
+#ifdef BN_MP_LCM_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t1, t2;
+
+
+  if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
+    return res;
+  }
+
+  /* t1 = get the GCD of the two inputs */
+  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+    goto LBL_T;
+  }
+
+  /* divide the smallest by the GCD */
+  if (mp_cmp_mag(a, b) == MP_LT) {
+     /* store quotient in t2 such that t2 * b is the LCM */
+     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(b, &t2, c);
+  } else {
+     /* store quotient in t2 such that t2 * a is the LCM */
+     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(a, &t2, c);
+  }
+
+  /* fix the sign to positive */
+  c->sign = MP_ZPOS;
+
+LBL_T:
+  mp_clear_multi (&t1, &t2, NULL);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_lcm.c */
+
+/* Start: bn_mp_lshd.c */
+#include "tommath.h"
+#ifdef BN_MP_LSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_lshd.c */
+
+/* Start: bn_mp_mod.c */
+#include "tommath.h"
+#ifdef BN_MP_MOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if (t.sign != b->sign) {
+    res = mp_add (b, &t, c);
+  } else {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mod.c */
+
+/* Start: bn_mp_mod_2d.c */
+#include "tommath.h"
+#ifdef BN_MP_MOD_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b >= (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &=
+    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mod_2d.c */
+
+/* Start: bn_mp_mod_d.c */
+#include "tommath.h"
+#ifdef BN_MP_MOD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+int
+mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+  return mp_div_d(a, b, NULL, c);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mod_d.c */
+
+/* Start: bn_mp_montgomery_calc_normalization.c */
+#include "tommath.h"
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b.  This saves alot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_montgomery_calc_normalization.c */
+
+/* Start: bn_mp_montgomery_reduce.c */
+#include "tommath.h"
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, digs;
+  mp_digit mu;
+
+  /* can the fast reduction [comba] method be used?
+   *
+   * Note that unlike in mul you're safely allowed *less*
+   * than the available columns [255 per default] since carries
+   * are fixed up in the inner loop.
+   */
+  digs = n->used * 2 + 1;
+  if ((digs < MP_WARRAY) &&
+      n->used <
+      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_mp_montgomery_reduce (x, n, rho);
+  }
+
+  /* grow the input as required */
+  if (x->alloc < digs) {
+    if ((res = mp_grow (x, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+  x->used = digs;
+
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * rho mod b
+     *
+     * The value of rho must be precalculated via
+     * montgomery_setup() such that
+     * it equals -1/n0 mod b this allows the
+     * following inner loop to reduce the
+     * input one digit at a time
+     */
+    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i */
+    {
+      register int iy;
+      register mp_digit *tmpn, *tmpx, u;
+      register mp_word r;
+
+      /* alias for digits of the modulus */
+      tmpn = n->dp;
+
+      /* alias for the digits of x [the input] */
+      tmpx = x->dp + ix;
+
+      /* set the carry to zero */
+      u = 0;
+
+      /* Multiply and add in place */
+      for (iy = 0; iy < n->used; iy++) {
+        /* compute product and sum */
+        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
+                  ((mp_word) u) + ((mp_word) * tmpx);
+
+        /* get carry */
+        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+        /* fix digit */
+        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+      }
+      /* At this point the ix'th digit of x should be zero */
+
+
+      /* propagate carries upwards as required*/
+      while (u) {
+        *tmpx   += u;
+        u        = *tmpx >> DIGIT_BIT;
+        *tmpx++ &= MP_MASK;
+      }
+    }
+  }
+
+  /* at this point the n.used'th least
+   * significant digits of x are all zero
+   * which means we can shift x to the
+   * right by n.used digits and the
+   * residue is unchanged.
+   */
+
+  /* x = x/b**n.used */
+  mp_clamp(x);
+  mp_rshd (x, n->used);
+
+  /* if x >= n then x = x - n */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_montgomery_reduce.c */
+
+/* Start: bn_mp_montgomery_setup.c */
+#include "tommath.h"
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_montgomery_setup.c */
+
+/* Start: bn_mp_mul.c */
+#include "tommath.h"
+#ifdef BN_MP_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+    res = mp_toom_mul(a, b, c);
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+  /* use Karatsuba? */
+  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+    res = mp_karatsuba_mul (a, b, c);
+  } else 
+#endif
+  {
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will 
+     * have less than MP_WARRAY digits and the number of 
+     * digits won't affect carry propagation
+     */
+    int     digs = a->used + b->used + 1;
+
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+    if ((digs < MP_WARRAY) &&
+        MIN(a->used, b->used) <= 
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else 
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mul.c */
+
+/* Start: bn_mp_mul_2.c */
+#include "tommath.h"
+#ifdef BN_MP_MUL_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accomodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+    
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+    
+      /* get what will be the *next* carry bit from the 
+       * MSB of the current digit 
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+      
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+      
+      /* copy the carry that would be from the source 
+       * digit into the next iteration 
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination 
+     * that we didn't write to 
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mul_2.c */
+
+/* Start: bn_mp_mul_2d.c */
+#include "tommath.h"
+#ifdef BN_MP_MUL_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+    
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mul_2d.c */
+
+/* Start: bn_mp_mul_d.c */
+#include "tommath.h"
+#ifdef BN_MP_MUL_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mul_d.c */
+
+/* Start: bn_mp_mulmod.c */
+#include "tommath.h"
+#ifdef BN_MP_MULMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* d = a * b (mod c) */
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_mulmod.c */
+
+/* Start: bn_mp_n_root.c */
+#include "tommath.h"
+#ifdef BN_MP_N_ROOT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* find the n'th root of an integer 
+ *
+ * Result found such that (c)**b <= a and (c+1)**b > a 
+ *
+ * This algorithm uses Newton's approximation 
+ * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
+ * which will find the root in log(N) time where 
+ * each step involves a fair bit.  This is not meant to 
+ * find huge roots [square and cube, etc].
+ */
+int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_int  t1, t2, t3;
+  int     res, neg;
+
+  /* input must be positive if b is even */
+  if ((b & 1) == 0 && a->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init (&t3)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  /* if a is negative fudge the sign but keep track */
+  neg     = a->sign;
+  a->sign = MP_ZPOS;
+
+  /* t2 = 2 */
+  mp_set (&t2, 2);
+
+  do {
+    /* t1 = t2 */
+    if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
+      goto LBL_T3;
+    }
+
+    /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
+    
+    /* t3 = t1**(b-1) */
+    if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {   
+      goto LBL_T3;
+    }
+
+    /* numerator */
+    /* t2 = t1**b */
+    if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {    
+      goto LBL_T3;
+    }
+
+    /* t2 = t1**b - a */
+    if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {  
+      goto LBL_T3;
+    }
+
+    /* denominator */
+    /* t3 = t1**(b-1) * b  */
+    if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {    
+      goto LBL_T3;
+    }
+
+    /* t3 = (t1**b - a)/(b * t1**(b-1)) */
+    if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {  
+      goto LBL_T3;
+    }
+
+    if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
+      goto LBL_T3;
+    }
+  }  while (mp_cmp (&t1, &t2) != MP_EQ);
+
+  /* result can be off by a few so check */
+  for (;;) {
+    if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
+      goto LBL_T3;
+    }
+
+    if (mp_cmp (&t2, a) == MP_GT) {
+      if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
+         goto LBL_T3;
+      }
+    } else {
+      break;
+    }
+  }
+
+  /* reset the sign of a first */
+  a->sign = neg;
+
+  /* set the result */
+  mp_exch (&t1, c);
+
+  /* set the sign of the result */
+  c->sign = neg;
+
+  res = MP_OKAY;
+
+LBL_T3:mp_clear (&t3);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_n_root.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_n_root.c */
+
+/* Start: bn_mp_neg.c */
+#include "tommath.h"
+#ifdef BN_MP_NEG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* b = -a */
+int mp_neg (mp_int * a, mp_int * b)
+{
+  int     res;
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  if (mp_iszero(b) != MP_YES) {
+     b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+  } else {
+     b->sign = MP_ZPOS;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_neg.c */
+
+/* Start: bn_mp_or.c */
+#include "tommath.h"
+#ifdef BN_MP_OR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* OR two ints together */
+int mp_or (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] |= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_or.c */
+
+/* Start: bn_mp_prime_fermat.c */
+#include "tommath.h"
+#ifdef BN_MP_PRIME_FERMAT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* performs one Fermat test.
+ * 
+ * If "a" were prime then b**a == b (mod a) since the order of
+ * the multiplicative sub-group would be phi(a) = a-1.  That means
+ * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
+ *
+ * Sets result to 1 if the congruence holds, or zero otherwise.
+ */
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  t;
+  int     err;
+
+  /* default to composite  */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* init t */
+  if ((err = mp_init (&t)) != MP_OKAY) {
+    return err;
+  }
+
+  /* compute t = b**a mod a */
+  if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
+    goto LBL_T;
+  }
+
+  /* is it equal to b? */
+  if (mp_cmp (&t, b) == MP_EQ) {
+    *result = MP_YES;
+  }
+
+  err = MP_OKAY;
+LBL_T:mp_clear (&t);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_prime_fermat.c */
+
+/* Start: bn_mp_prime_is_divisible.c */
+#include "tommath.h"
+#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* determines if an integers is divisible by one 
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+int mp_prime_is_divisible (mp_int * a, int *result)
+{
+  int     err, ix;
+  mp_digit res;
+
+  /* default to not */
+  *result = MP_NO;
+
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+    /* what is a mod LBL_prime_tab[ix] */
+    if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+      return err;
+    }
+
+    /* is the residue zero? */
+    if (res == 0) {
+      *result = MP_YES;
+      return MP_OKAY;
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_divisible.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_prime_is_divisible.c */
+
+/* Start: bn_mp_prime_is_prime.c */
+#include "tommath.h"
+#ifdef BN_MP_PRIME_IS_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+  mp_int  b;
+  int     ix, err, res;
+
+  /* default to no */
+  *result = MP_NO;
+
+  /* valid value of t? */
+  if (t <= 0 || t > PRIME_SIZE) {
+    return MP_VAL;
+  }
+
+  /* is the input equal to one of the primes in the table? */
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+         *result = 1;
+         return MP_OKAY;
+      }
+  }
+
+  /* first perform trial division */
+  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+    return err;
+  }
+
+  /* return if it was trivially divisible */
+  if (res == MP_YES) {
+    return MP_OKAY;
+  }
+
+  /* now perform the miller-rabin rounds */
+  if ((err = mp_init (&b)) != MP_OKAY) {
+    return err;
+  }
+
+  for (ix = 0; ix < t; ix++) {
+    /* set the prime */
+    mp_set (&b, ltm_prime_tab[ix]);
+
+    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+      goto LBL_B;
+    }
+
+    if (res == MP_NO) {
+      goto LBL_B;
+    }
+  }
+
+  /* passed the test */
+  *result = MP_YES;
+LBL_B:mp_clear (&b);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_prime_is_prime.c */
+
+/* Start: bn_mp_prime_miller_rabin.c */
+#include "tommath.h"
+#ifdef BN_MP_PRIME_MILLER_RABIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* Miller-Rabin test of "a" to the base of "b" as described in 
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often 
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  n1, y, r;
+  int     s, j, err;
+
+  /* default */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }     
+
+  /* get n1 = a - 1 */
+  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+    return err;
+  }
+  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* set 2**s * r = n1 */
+  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* count the number of least significant bits
+   * which are zero
+   */
+  s = mp_cnt_lsb(&r);
+
+  /* now divide n - 1 by 2**s */
+  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+    goto LBL_R;
+  }
+
+  /* compute y = b**r mod a */
+  if ((err = mp_init (&y)) != MP_OKAY) {
+    goto LBL_R;
+  }
+  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+    goto LBL_Y;
+  }
+
+  /* if y != 1 and y != n1 do */
+  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+    j = 1;
+    /* while j <= s-1 and y != n1 */
+    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+         goto LBL_Y;
+      }
+
+      /* if y == 1 then composite */
+      if (mp_cmp_d (&y, 1) == MP_EQ) {
+         goto LBL_Y;
+      }
+
+      ++j;
+    }
+
+    /* if y != n1 then composite */
+    if (mp_cmp (&y, &n1) != MP_EQ) {
+      goto LBL_Y;
+    }
+  }
+
+  /* probably prime now */
+  *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_prime_miller_rabin.c */
+
+/* Start: bn_mp_prime_next_prime.c */
+#include "tommath.h"
+#ifdef BN_MP_PRIME_NEXT_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+{
+   int      err, res, x, y;
+   mp_digit res_tab[PRIME_SIZE], step, kstep;
+   mp_int   b;
+
+   /* ensure t is valid */
+   if (t <= 0 || t > PRIME_SIZE) {
+      return MP_VAL;
+   }
+
+   /* force positive */
+   a->sign = MP_ZPOS;
+
+   /* simple algo if a is less than the largest prime in the table */
+   if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
+      /* find which prime it is bigger than */
+      for (x = PRIME_SIZE - 2; x >= 0; x--) {
+          if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
+             if (bbs_style == 1) {
+                /* ok we found a prime smaller or
+                 * equal [so the next is larger]
+                 *
+                 * however, the prime must be
+                 * congruent to 3 mod 4
+                 */
+                if ((ltm_prime_tab[x + 1] & 3) != 3) {
+                   /* scan upwards for a prime congruent to 3 mod 4 */
+                   for (y = x + 1; y < PRIME_SIZE; y++) {
+                       if ((ltm_prime_tab[y] & 3) == 3) {
+                          mp_set(a, ltm_prime_tab[y]);
+                          return MP_OKAY;
+                       }
+                   }
+                }
+             } else {
+                mp_set(a, ltm_prime_tab[x + 1]);
+                return MP_OKAY;
+             }
+          }
+      }
+      /* at this point a maybe 1 */
+      if (mp_cmp_d(a, 1) == MP_EQ) {
+         mp_set(a, 2);
+         return MP_OKAY;
+      }
+      /* fall through to the sieve */
+   }
+
+   /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
+   if (bbs_style == 1) {
+      kstep   = 4;
+   } else {
+      kstep   = 2;
+   }
+
+   /* at this point we will use a combination of a sieve and Miller-Rabin */
+
+   if (bbs_style == 1) {
+      /* if a mod 4 != 3 subtract the correct value to make it so */
+      if ((a->dp[0] & 3) != 3) {
+         if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
+      }
+   } else {
+      if (mp_iseven(a) == 1) {
+         /* force odd */
+         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
+            return err;
+         }
+      }
+   }
+
+   /* generate the restable */
+   for (x = 1; x < PRIME_SIZE; x++) {
+      if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
+         return err;
+      }
+   }
+
+   /* init temp used for Miller-Rabin Testing */
+   if ((err = mp_init(&b)) != MP_OKAY) {
+      return err;
+   }
+
+   for (;;) {
+      /* skip to the next non-trivially divisible candidate */
+      step = 0;
+      do {
+         /* y == 1 if any residue was zero [e.g. cannot be prime] */
+         y     =  0;
+
+         /* increase step to next candidate */
+         step += kstep;
+
+         /* compute the new residue without using division */
+         for (x = 1; x < PRIME_SIZE; x++) {
+             /* add the step to each residue */
+             res_tab[x] += kstep;
+
+             /* subtract the modulus [instead of using division] */
+             if (res_tab[x] >= ltm_prime_tab[x]) {
+                res_tab[x]  -= ltm_prime_tab[x];
+             }
+
+             /* set flag if zero */
+             if (res_tab[x] == 0) {
+                y = 1;
+             }
+         }
+      } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
+
+      /* add the step */
+      if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+
+      /* if didn't pass sieve and step == MAX then skip test */
+      if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
+         continue;
+      }
+
+      /* is this prime? */
+      for (x = 0; x < t; x++) {
+          mp_set(&b, ltm_prime_tab[t]);
+          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
+             goto LBL_ERR;
+          }
+          if (res == MP_NO) {
+             break;
+          }
+      }
+
+      if (res == MP_YES) {
+         break;
+      }
+   }
+
+   err = MP_OKAY;
+LBL_ERR:
+   mp_clear(&b);
+   return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_next_prime.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_prime_next_prime.c */
+
+/* Start: bn_mp_prime_rabin_miller_trials.c */
+#include "tommath.h"
+#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+
+static const struct {
+   int k, t;
+} sizes[] = {
+{   128,    28 },
+{   256,    16 },
+{   384,    10 },
+{   512,     7 },
+{   640,     6 },
+{   768,     5 },
+{   896,     4 },
+{  1024,     4 }
+};
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+       if (sizes[x].k == size) {
+          return sizes[x].t;
+       } else if (sizes[x].k > size) {
+          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+       }
+   }
+   return sizes[x-1].t + 1;
+}
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_prime_rabin_miller_trials.c */
+
+/* Start: bn_mp_prime_random_ex.c */
+#include "tommath.h"
+#ifdef BN_MP_PRIME_RANDOM_EX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ * 
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
+{
+   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+   int res, err, bsize, maskOR_msb_offset;
+
+   /* sanity check the input */
+   if (size <= 1 || t <= 0) {
+      return MP_VAL;
+   }
+
+   /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
+   if (flags & LTM_PRIME_SAFE) {
+      flags |= LTM_PRIME_BBS;
+   }
+
+   /* calc the byte size */
+   bsize = (size>>3) + ((size&7)?1:0);
+
+   /* we need a buffer of bsize bytes */
+   tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
+   if (tmp == NULL) {
+      return MP_MEM;
+   }
+
+   /* calc the maskAND value for the MSbyte*/
+   maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));
+
+   /* calc the maskOR_msb */
+   maskOR_msb        = 0;
+   maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
+   if (flags & LTM_PRIME_2MSB_ON) {
+      maskOR_msb       |= 0x80 >> ((9 - size) & 7);
+   }  
+
+   /* get the maskOR_lsb */
+   maskOR_lsb         = 1;
+   if (flags & LTM_PRIME_BBS) {
+      maskOR_lsb     |= 3;
+   }
+
+   do {
+      /* read the bytes */
+      if (cb(tmp, bsize, dat) != bsize) {
+         err = MP_VAL;
+         goto error;
+      }
+ 
+      /* work over the MSbyte */
+      tmp[0]    &= maskAND;
+      tmp[0]    |= 1 << ((size - 1) & 7);
+
+      /* mix in the maskORs */
+      tmp[maskOR_msb_offset]   |= maskOR_msb;
+      tmp[bsize-1]             |= maskOR_lsb;
+
+      /* read it in */
+      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY)     { goto error; }
+
+      /* is it prime? */
+      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
+      if (res == MP_NO) {  
+         continue;
+      }
+
+      if (flags & LTM_PRIME_SAFE) {
+         /* see if (a-1)/2 is prime */
+         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY)                    { goto error; }
+         if ((err = mp_div_2(a, a)) != MP_OKAY)                       { goto error; }
+ 
+         /* is it prime? */
+         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)        { goto error; }
+      }
+   } while (res == MP_NO);
+
+   if (flags & LTM_PRIME_SAFE) {
+      /* restore a to the original value */
+      if ((err = mp_mul_2(a, a)) != MP_OKAY)                          { goto error; }
+      if ((err = mp_add_d(a, 1, a)) != MP_OKAY)                       { goto error; }
+   }
+
+   err = MP_OKAY;
+error:
+   XFREE(tmp);
+   return err;
+}
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_prime_random_ex.c */
+
+/* Start: bn_mp_radix_size.c */
+#include "tommath.h"
+#ifdef BN_MP_RADIX_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* returns size of ASCII reprensentation */
+int mp_radix_size (mp_int * a, int radix, int *size)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+
+  *size = 0;
+
+  /* special case for binary */
+  if (radix == 2) {
+    *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+    return MP_OKAY;
+  }
+
+  /* make sure the radix is in range */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  if (mp_iszero(a) == MP_YES) {
+    *size = 2;
+    return MP_OKAY;
+  }
+
+  /* digs is the digit count */
+  digs = 0;
+
+  /* if it's negative add one for the sign */
+  if (a->sign == MP_NEG) {
+    ++digs;
+  }
+
+  /* init a copy of the input */
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* force temp to positive */
+  t.sign = MP_ZPOS; 
+
+  /* fetch out all of the digits */
+  while (mp_iszero (&t) == MP_NO) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    ++digs;
+  }
+  mp_clear (&t);
+
+  /* return digs + 1, the 1 is for the NULL byte that would be required. */
+  *size = digs + 1;
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_radix_size.c */
+
+/* Start: bn_mp_radix_smap.c */
+#include "tommath.h"
+#ifdef BN_MP_RADIX_SMAP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_radix_smap.c */
+
+/* Start: bn_mp_rand.c */
+#include "tommath.h"
+#ifdef BN_MP_RAND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* makes a pseudo-random int of a given size */
+int
+mp_rand (mp_int * a, int digits)
+{
+  int     res;
+  mp_digit d;
+
+  mp_zero (a);
+  if (digits <= 0) {
+    return MP_OKAY;
+  }
+
+  /* first place a random non-zero digit */
+  do {
+    d = ((mp_digit) abs (rand ())) & MP_MASK;
+  } while (d == 0);
+
+  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
+    return res;
+  }
+
+  while (--digits > 0) {
+    if ((res = mp_lshd (a, 1)) != MP_OKAY) {
+      return res;
+    }
+
+    if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_rand.c */
+
+/* Start: bn_mp_read_radix.c */
+#include "tommath.h"
+#ifdef BN_MP_READ_RADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, const char *str, int radix)
+{
+  int     y, res, neg;
+  char    ch;
+
+  /* zero the digit bignum */
+  mp_zero(a);
+
+  /* make sure the radix is ok */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* if the leading digit is a 
+   * minus set the sign to negative. 
+   */
+  if (*str == '-') {
+    ++str;
+    neg = MP_NEG;
+  } else {
+    neg = MP_ZPOS;
+  }
+
+  /* set the integer to the default of zero */
+  mp_zero (a);
+  
+  /* process each digit of the string */
+  while (*str) {
+    /* if the radix < 36 the conversion is case insensitive
+     * this allows numbers like 1AB and 1ab to represent the same  value
+     * [e.g. in hex]
+     */
+    ch = (char) ((radix < 36) ? toupper (*str) : *str);
+    for (y = 0; y < 64; y++) {
+      if (ch == mp_s_rmap[y]) {
+         break;
+      }
+    }
+
+    /* if the char was found in the map 
+     * and is less than the given radix add it
+     * to the number, otherwise exit the loop. 
+     */
+    if (y < radix) {
+      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+         return res;
+      }
+      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+         return res;
+      }
+    } else {
+      break;
+    }
+    ++str;
+  }
+  
+  /* set the sign only if a != 0 */
+  if (mp_iszero(a) != 1) {
+     a->sign = neg;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_read_radix.c */
+
+/* Start: bn_mp_read_signed_bin.c */
+#include "tommath.h"
+#ifdef BN_MP_READ_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* read signed bin, big endian, first byte is 0==positive or 1==negative */
+int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c)
+{
+  int     res;
+
+  /* read magnitude */
+  if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* first byte is 0 for positive, non-zero for negative */
+  if (b[0] == 0) {
+     a->sign = MP_ZPOS;
+  } else {
+     a->sign = MP_NEG;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_read_signed_bin.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_read_signed_bin.c */
+
+/* Start: bn_mp_read_unsigned_bin.c */
+#include "tommath.h"
+#ifdef BN_MP_READ_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+  int     res;
+
+  /* make sure there are at least two digits */
+  if (a->alloc < 2) {
+     if ((res = mp_grow(a, 2)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero the int */
+  mp_zero (a);
+
+  /* read the bytes in */
+  while (c-- > 0) {
+    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+      return res;
+    }
+
+#ifndef MP_8BIT
+      a->dp[0] |= *b++;
+      a->used += 1;
+#else
+      a->dp[0] = (*b & MP_MASK);
+      a->dp[1] |= ((*b++ >> 7U) & 1);
+      a->used += 2;
+#endif
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_read_unsigned_bin.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_read_unsigned_bin.c */
+
+/* Start: bn_mp_reduce.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is 
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);         
+
+  /* according to HAC this optimization is ok */
+  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else 
+    { 
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);         
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    mp_set (&q, 1);
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+      goto CLEANUP;
+    if ((res = mp_add (x, &q, x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+  
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce.c */
+
+/* Start: bn_mp_reduce_2k.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (d != 1) {
+      /* q = q * d */
+      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
+         goto ERR;
+      }
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce_2k.c */
+
+/* Start: bn_mp_reduce_2k_l.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d 
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   /* q = q * d */
+   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 
+      goto ERR;
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce_2k_l.c */
+
+/* Start: bn_mp_reduce_2k_setup.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+   int res, p;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(a);
+   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   *d = tmp.dp[0];
+   mp_clear(&tmp);
+   return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce_2k_setup.c */
+
+/* Start: bn_mp_reduce_2k_setup_l.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_2K_SETUP_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+   int    res;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+ERR:
+   mp_clear(&tmp);
+   return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce_2k_setup_l.c */
+
+/* Start: bn_mp_reduce_is_2k.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_IS_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+   int ix, iy, iw;
+   mp_digit iz;
+   
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      iy = mp_count_bits(a);
+      iz = 1;
+      iw = 1;
+    
+      /* Test every bit from the second digit up, must be 1 */
+      for (ix = DIGIT_BIT; ix < iy; ix++) {
+          if ((a->dp[iw] & iz) == 0) {
+             return MP_NO;
+          }
+          iz <<= 1;
+          if (iz > (mp_digit)MP_MASK) {
+             ++iw;
+             iz = 1;
+          }
+      }
+   }
+   return MP_YES;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce_is_2k.c */
+
+/* Start: bn_mp_reduce_is_2k_l.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_IS_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+   int ix, iy;
+   
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      /* if more than half of the digits are -1 we're sold */
+      for (iy = ix = 0; ix < a->used; ix++) {
+          if (a->dp[ix] == MP_MASK) {
+              ++iy;
+          }
+      }
+      return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+      
+   }
+   return MP_NO;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce_is_2k_l.c */
+
+/* Start: bn_mp_reduce_setup.c */
+#include "tommath.h"
+#ifdef BN_MP_REDUCE_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+  
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_reduce_setup.c */
+
+/* Start: bn_mp_rshd.c */
+#include "tommath.h"
+#ifdef BN_MP_RSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where 
+     * the window is b-digits long and digits from 
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+  
+  /* remove excess digits */
+  a->used -= b;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_rshd.c */
+
+/* Start: bn_mp_set.c */
+#include "tommath.h"
+#ifdef BN_MP_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+  mp_zero (a);
+  a->dp[0] = b & MP_MASK;
+  a->used  = (a->dp[0] != 0) ? 1 : 0;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_set.c */
+
+/* Start: bn_mp_set_int.c */
+#include "tommath.h"
+#ifdef BN_MP_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* set a 32-bit const */
+int mp_set_int (mp_int * a, unsigned long b)
+{
+  int     x, res;
+
+  mp_zero (a);
+  
+  /* set four bits at a time */
+  for (x = 0; x < 8; x++) {
+    /* shift the number up four bits */
+    if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
+      return res;
+    }
+
+    /* OR in the top four bits of the source */
+    a->dp[0] |= (b >> 28) & 15;
+
+    /* shift the source up to the next four bits */
+    b <<= 4;
+
+    /* ensure that digits are not clamped off */
+    a->used += 1;
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_set_int.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_set_int.c */
+
+/* Start: bn_mp_shrink.c */
+#include "tommath.h"
+#ifdef BN_MP_SHRINK_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* shrink a bignum */
+int mp_shrink (mp_int * a)
+{
+  mp_digit *tmp;
+  if (a->alloc != a->used && a->used > 0) {
+    if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
+      return MP_MEM;
+    }
+    a->dp    = tmp;
+    a->alloc = a->used;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_shrink.c */
+
+/* Start: bn_mp_signed_bin_size.c */
+#include "tommath.h"
+#ifdef BN_MP_SIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* get the size for an signed equivalent */
+int mp_signed_bin_size (mp_int * a)
+{
+  return 1 + mp_unsigned_bin_size (a);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_signed_bin_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_signed_bin_size.c */
+
+/* Start: bn_mp_sqr.c */
+#include "tommath.h"
+#ifdef BN_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+#ifdef BN_MP_TOOM_SQR_C
+  /* use Toom-Cook? */
+  if (a->used >= TOOM_SQR_CUTOFF) {
+    res = mp_toom_sqr(a, b);
+  /* Karatsuba? */
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+    res = mp_karatsuba_sqr (a, b);
+  } else 
+#endif
+  {
+#ifdef BN_FAST_S_MP_SQR_C
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < MP_WARRAY && 
+         a->used < 
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
+      res = s_mp_sqr (a, b);
+#else
+      res = MP_VAL;
+#endif
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_sqr.c */
+
+/* Start: bn_mp_sqrmod.c */
+#include "tommath.h"
+#ifdef BN_MP_SQRMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* c = a * a (mod b) */
+int
+mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, b, c);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_sqrmod.c */
+
+/* Start: bn_mp_sqrt.c */
+#include "tommath.h"
+#ifdef BN_MP_SQRT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* this function is less generic than mp_n_root, simpler and faster */
+int mp_sqrt(mp_int *arg, mp_int *ret) 
+{
+  int res;
+  mp_int t1,t2;
+
+  /* must be positive */
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* easy out */
+  if (mp_iszero(arg) == MP_YES) {
+    mp_zero(ret);
+    return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init(&t2)) != MP_OKAY) {
+    goto E2;
+  }
+
+  /* First approx. (not very bad for large arg) */
+  mp_rshd (&t1,t1.used/2);
+
+  /* t1 > 0  */ 
+  if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  /* And now t1 > sqrt(arg) */
+  do { 
+    if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    /* t1 >= sqrt(arg) >= t2 at this point */
+  } while (mp_cmp_mag(&t1,&t2) == MP_GT);
+
+  mp_exch(&t1,ret);
+
+E1: mp_clear(&t2);
+E2: mp_clear(&t1);
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_sqrt.c */
+
+/* Start: bn_mp_sub.c */
+#include "tommath.h"
+#ifdef BN_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_sub.c */
+
+/* Start: bn_mp_sub_d.c */
+#include "tommath.h"
+#ifdef BN_MP_SUB_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* single digit subtraction */
+int
+mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit *tmpa, *tmpc, mu;
+  int       res, ix, oldused;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative just do an unsigned
+   * addition [with fudged signs]
+   */
+  if (a->sign == MP_NEG) {
+     a->sign = MP_ZPOS;
+     res     = mp_add_d(a, b, c);
+     a->sign = c->sign = MP_NEG;
+
+     /* clamp */
+     mp_clamp(c);
+
+     return res;
+  }
+
+  /* setup regs */
+  oldused = c->used;
+  tmpa    = a->dp;
+  tmpc    = c->dp;
+
+  /* if a <= b simply fix the single digit */
+  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+     if (a->used == 1) {
+        *tmpc++ = b - *tmpa;
+     } else {
+        *tmpc++ = b;
+     }
+     ix      = 1;
+
+     /* negative/1digit */
+     c->sign = MP_NEG;
+     c->used = 1;
+  } else {
+     /* positive/size */
+     c->sign = MP_ZPOS;
+     c->used = a->used;
+
+     /* subtract first digit */
+     *tmpc    = *tmpa++ - b;
+     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+     *tmpc++ &= MP_MASK;
+
+     /* handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc    = *tmpa++ - mu;
+        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+        *tmpc++ &= MP_MASK;
+     }
+  }
+
+  /* zero excess digits */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_sub_d.c */
+
+/* Start: bn_mp_submod.c */
+#include "tommath.h"
+#ifdef BN_MP_SUBMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* d = a - b (mod c) */
+int
+mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_submod.c */
+
+/* Start: bn_mp_to_signed_bin.c */
+#include "tommath.h"
+#ifdef BN_MP_TO_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin (mp_int * a, unsigned char *b)
+{
+  int     res;
+
+  if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
+    return res;
+  }
+  b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_to_signed_bin.c */
+
+/* Start: bn_mp_to_signed_bin_n.c */
+#include "tommath.h"
+#ifdef BN_MP_TO_SIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+   if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
+      return MP_VAL;
+   }
+   *outlen = mp_signed_bin_size(a);
+   return mp_to_signed_bin(a, b);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin_n.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_to_signed_bin_n.c */
+
+/* Start: bn_mp_to_unsigned_bin.c */
+#include "tommath.h"
+#ifdef BN_MP_TO_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+  int     x, res;
+  mp_int  t;
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  x = 0;
+  while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+      b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+  bn_reverse (b, x);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_to_unsigned_bin.c */
+
+/* Start: bn_mp_to_unsigned_bin_n.c */
+#include "tommath.h"
+#ifdef BN_MP_TO_UNSIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+   if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
+      return MP_VAL;
+   }
+   *outlen = mp_unsigned_bin_size(a);
+   return mp_to_unsigned_bin(a, b);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin_n.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_to_unsigned_bin_n.c */
+
+/* Start: bn_mp_toom_mul.c */
+#include "tommath.h"
+#ifdef BN_MP_TOOM_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* multiplication using the Toom-Cook 3-way algorithm 
+ *
+ * Much more complicated than Karatsuba but has a lower 
+ * asymptotic running time of O(N**1.464).  This algorithm is 
+ * only particularly useful on VERY large inputs 
+ * (we're talking 1000s of digits here...).
+*/
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
+    int res, B;
+        
+    /* init temps */
+    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
+                             &a0, &a1, &a2, &b0, &b1, 
+                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
+       return res;
+    }
+    
+    /* B */
+    B = MIN(a->used, b->used) / 3;
+    
+    /* a = a2 * B**2 + a1 * B + a0 */
+    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a1, B);
+    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a2, B*2);
+    
+    /* b = b2 * B**2 + b1 * B + b0 */
+    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&b1, B);
+    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
+
+    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&b2, B*2);
+    
+    /* w0 = a0*b0 */
+    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w4 = a2 * b2 */
+    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
+    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
+    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+
+    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
+    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* now solve the matrix 
+    
+       0  0  0  0  1
+       1  2  4  8  16
+       1  1  1  1  1
+       16 8  4  2  1
+       1  0  0  0  0
+       
+       using 12 subtractions, 4 shifts, 
+              2 small divisions and 1 small multiplication 
+     */
+     
+     /* r1 - r4 */
+     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r0 */
+     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/2 */
+     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/2 */
+     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r2 - r0 - r4 */
+     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - 8r0 */
+     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - 8r4 */
+     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* 3r2 - r1 - r3 */
+     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/3 */
+     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/3 */
+     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     
+     /* at this point shift W[n] by B*n */
+     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+        goto ERR;
+     }     
+     
+     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
+        goto ERR;
+     }     
+     
+ERR:
+     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
+                    &a0, &a1, &a2, &b0, &b1, 
+                    &b2, &tmp1, &tmp2, NULL);
+     return res;
+}     
+     
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_toom_mul.c */
+
+/* Start: bn_mp_toom_sqr.c */
+#include "tommath.h"
+#ifdef BN_MP_TOOM_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* squaring using Toom-Cook 3-way algorithm */
+int
+mp_toom_sqr(mp_int *a, mp_int *b)
+{
+    mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+    int res, B;
+
+    /* init temps */
+    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
+       return res;
+    }
+
+    /* B */
+    B = a->used / 3;
+
+    /* a = a2 * B**2 + a1 * B + a0 */
+    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a1, B);
+    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a2, B*2);
+
+    /* w0 = a0*a0 */
+    if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w4 = a2 * a2 */
+    if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w1 = (a2 + 2(a1 + 2a0))**2 */
+    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w3 = (a0 + 2(a1 + 2a2))**2 */
+    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
+       goto ERR;
+    }
+
+
+    /* w2 = (a2 + a1 + a0)**2 */
+    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* now solve the matrix
+
+       0  0  0  0  1
+       1  2  4  8  16
+       1  1  1  1  1
+       16 8  4  2  1
+       1  0  0  0  0
+
+       using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+     */
+
+     /* r1 - r4 */
+     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r0 */
+     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/2 */
+     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/2 */
+     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r2 - r0 - r4 */
+     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - 8r0 */
+     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - 8r4 */
+     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* 3r2 - r1 - r3 */
+     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/3 */
+     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/3 */
+     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+
+     /* at this point shift W[n] by B*n */
+     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+        goto ERR;
+     }
+
+     if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
+        goto ERR;
+     }
+
+ERR:
+     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
+     return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_toom_sqr.c */
+
+/* Start: bn_mp_toradix.c */
+#include "tommath.h"
+#ifdef BN_MP_TORADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64) */
+int mp_toradix (mp_int * a, char *str, int radix)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+  char   *_s = str;
+
+  /* check range of the radix */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (mp_iszero(a) == 1) {
+     *str++ = '0';
+     *str = '\0';
+     return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* if it is negative output a - */
+  if (t.sign == MP_NEG) {
+    ++_s;
+    *str++ = '-';
+    t.sign = MP_ZPOS;
+  }
+
+  digs = 0;
+  while (mp_iszero (&t) == 0) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    *str++ = mp_s_rmap[d];
+    ++digs;
+  }
+
+  /* reverse the digits of the string.  In this case _s points
+   * to the first digit [exluding the sign] of the number]
+   */
+  bn_reverse ((unsigned char *)_s, digs);
+
+  /* append a NULL so the string is properly terminated */
+  *str = '\0';
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toradix.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_toradix.c */
+
+/* Start: bn_mp_toradix_n.c */
+#include "tommath.h"
+#ifdef BN_MP_TORADIX_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64) 
+ *
+ * Stores upto maxlen-1 chars and always a NULL byte 
+ */
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+  char   *_s = str;
+
+  /* check range of the maxlen, radix */
+  if (maxlen < 2 || radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (mp_iszero(a) == MP_YES) {
+     *str++ = '0';
+     *str = '\0';
+     return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* if it is negative output a - */
+  if (t.sign == MP_NEG) {
+    /* we have to reverse our digits later... but not the - sign!! */
+    ++_s;
+
+    /* store the flag and mark the number as positive */
+    *str++ = '-';
+    t.sign = MP_ZPOS;
+ 
+    /* subtract a char */
+    --maxlen;
+  }
+
+  digs = 0;
+  while (mp_iszero (&t) == 0) {
+    if (--maxlen < 1) {
+       /* no more room */
+       break;
+    }
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    *str++ = mp_s_rmap[d];
+    ++digs;
+  }
+
+  /* reverse the digits of the string.  In this case _s points
+   * to the first digit [exluding the sign] of the number
+   */
+  bn_reverse ((unsigned char *)_s, digs);
+
+  /* append a NULL so the string is properly terminated */
+  *str = '\0';
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_toradix_n.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_toradix_n.c */
+
+/* Start: bn_mp_unsigned_bin_size.c */
+#include "tommath.h"
+#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* get the size for an unsigned equivalent */
+int mp_unsigned_bin_size (mp_int * a)
+{
+  int     size = mp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_unsigned_bin_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_unsigned_bin_size.c */
+
+/* Start: bn_mp_xor.c */
+#include "tommath.h"
+#ifdef BN_MP_XOR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* XOR two ints together */
+int
+mp_xor (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+     t.dp[ix] ^= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_xor.c */
+
+/* Start: bn_mp_zero.c */
+#include "tommath.h"
+#ifdef BN_MP_ZERO_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+  int       n;
+  mp_digit *tmp;
+
+  a->sign = MP_ZPOS;
+  a->used = 0;
+
+  tmp = a->dp;
+  for (n = 0; n < a->alloc; n++) {
+     *tmp++ = 0;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_mp_zero.c */
+
+/* Start: bn_prime_tab.c */
+#include "tommath.h"
+#ifdef BN_PRIME_TAB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+const mp_digit ltm_prime_tab[] = {
+  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+  0x0083,
+  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_prime_tab.c */
+
+/* Start: bn_reverse.c */
+#include "tommath.h"
+#ifdef BN_REVERSE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* reverse an array, used for radix code */
+void
+bn_reverse (unsigned char *s, int len)
+{
+  int     ix, iy;
+  unsigned char t;
+
+  ix = 0;
+  iy = len - 1;
+  while (ix < iy) {
+    t     = s[ix];
+    s[ix] = s[iy];
+    s[iy] = t;
+    ++ix;
+    --iy;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_reverse.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_reverse.c */
+
+/* Start: bn_s_mp_add.c */
+#include "tommath.h"
+#ifdef BN_S_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min, max;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min = b->used;
+    max = a->used;
+    x = a;
+  } else {
+    min = a->used;
+    max = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max + 1) {
+    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max + 1;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B 
+     * if A or B has more digits add those in 
+     */
+    if (min != max) {
+      for (; i < max; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above oldused */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_s_mp_add.c */
+
+/* Start: bn_s_mp_exptmod.c */
+#include "tommath.h"
+#ifdef BN_S_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+  int (*redux)(mp_int*,mp_int*,mp_int*);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err; 
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto LBL_M;
+  }
+  
+  if (redmode == 0) {
+     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce;
+  } else {
+     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce_2k_l;
+  }    
+
+  /* create M table
+   *
+   * The M table contains powers of the base, 
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not 
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring 
+   * M[1] (winsize-1) times 
+   */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    /* square it */
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
+                       &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+
+    /* reduce modulo P */
+    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+  mp_set (&res, 1);
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_s_mp_exptmod.c */
+
+/* Start: bn_s_mp_mul_digs.c */
+#include "tommath.h"
+#ifdef BN_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((digs) < MP_WARRAY) &&
+      MIN (a->used, b->used) < 
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+    
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+    
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_s_mp_mul_digs.c */
+
+/* Start: bn_s_mp_mul_high_digs.c */
+#include "tommath.h"
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+  if (((a->used + b->used + 1) < MP_WARRAY)
+      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+#endif
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_s_mp_mul_high_digs.c */
+
+/* Start: bn_s_mp_sqr.c */
+#include "tommath.h"
+#ifdef BN_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+    
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_s_mp_sqr.c */
+
+/* Start: bn_s_mp_sub.c */
+#include "tommath.h"
+#ifdef BN_S_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min, max;
+
+  /* find sizes */
+  min = b->used;
+  max = a->used;
+
+  /* init result */
+  if (c->alloc < max) {
+    if ((res = mp_grow (c, max)) != MP_OKAY) {
+      return res;
+    }
+  }
+  olduse = c->used;
+  c->used = max;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bn_s_mp_sub.c */
+
+/* Start: bncore.c */
+#include "tommath.h"
+#ifdef BNCORE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://libtom.org
+ */
+
+/* Known optimal configurations
+
+ CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
+-------------------------------------------------------------
+ Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)
+ AMD Athlon64           /GCC v3.4.4   /        80/       120/LTM 0.35
+ 
+*/
+
+int     KARATSUBA_MUL_CUTOFF = 80,      /* Min. number of digits before Karatsuba multiplication is used. */
+        KARATSUBA_SQR_CUTOFF = 120,     /* Min. number of digits before Karatsuba squaring is used. */
+        
+        TOOM_MUL_CUTOFF      = 350,      /* no optimal values of these are known yet so set em high */
+        TOOM_SQR_CUTOFF      = 400; 
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bncore.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
+
+/* End: bncore.c */
+
+
+/* EOF */
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/tommath.h
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/tommath.h	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,589 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis_at_[hidden], http://math.libtomcrypt.com
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "tommath_class.h"
+
+#ifndef MIN
+   #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+   #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define  OPT_CAST(x)  (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define  OPT_CAST(x)
+
+#endif
+
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__) 
+   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+      #define MP_64BIT
+   #endif
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+   typedef unsigned char      mp_digit;
+   typedef unsigned short     mp_word;
+#elif defined(MP_16BIT)
+   typedef unsigned short     mp_digit;
+   typedef unsigned long      mp_word;
+#elif defined(MP_64BIT)
+   /* for GCC only on supported platforms */
+#ifndef CRYPT
+   typedef unsigned long long ulong64;
+   typedef signed long long   long64;
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef unsigned long      mp_word __attribute__ ((mode(TI)));
+
+   #define DIGIT_BIT          60
+#else
+   /* this is the default case, 28-bit digits */
+   
+   /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+   #if defined(_MSC_VER) || defined(__BORLANDC__) 
+      typedef unsigned __int64   ulong64;
+      typedef signed __int64     long64;
+   #else
+      typedef unsigned long long ulong64;
+      typedef signed long long   long64;
+   #endif
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef ulong64            mp_word;
+
+#ifdef MP_31BIT   
+   /* this is an extension that uses 31-bit digits */
+   #define DIGIT_BIT          31
+#else
+   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+   #define DIGIT_BIT          28
+   #define MP_28BIT
+#endif   
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+   /* default to libc stuff */
+   #ifndef XMALLOC 
+       #define XMALLOC  malloc
+       #define XFREE    free
+       #define XREALLOC realloc
+       #define XCALLOC  calloc
+   #else
+      /* prototypes for our heap functions */
+      extern void *XMALLOC(size_t n);
+      extern void *XREALLOC(void *p, size_t n);
+      extern void *XCALLOC(size_t n, size_t s);
+      extern void XFREE(void *p);
+   #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT     DIGIT_BIT
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX     MP_MASK
+
+/* equalities */
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+#define MP_RANGE      MP_VAL
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
+
+typedef int           mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+           KARATSUBA_SQR_CUTOFF,
+           TOOM_MUL_CUTOFF,
+           TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+   #ifndef MP_LOW_MEM
+      #define MP_PREC                 32     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif   
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m)    ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m)    ((m)->sign)
+
+/* error code to char* string */
+const char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b  */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a  */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* returns true if a can be reduced with mp_reduce_2k_l */
+int mp_reduce_is_2k_l(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+   #define PRIME_SIZE      31
+#else
+   #define PRIME_SIZE      256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit ltm_prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96 
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases.  Also performs an initial sieve of trial
+ * division.  Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4 
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ * 
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a,  unsigned char *b);
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_read_radix(mp_int *a, const char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp)           mp_signed_bin_size(mp)
+#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S)     mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtommath/tommath.h,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/03/31 14:18:44 $ */
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/tommath_class.h
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/tommath_class.h	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,1004 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#define BN_MP_DR_IS_MODULUS_C
+#define BN_MP_DR_REDUCE_C
+#define BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#define BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#define BN_MP_PRIME_FERMAT_C
+#define BN_MP_PRIME_IS_DIVISIBLE_C
+#define BN_MP_PRIME_IS_PRIME_C
+#define BN_MP_PRIME_MILLER_RABIN_C
+#define BN_MP_PRIME_NEXT_PRIME_C
+#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#define BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_L_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_2K_SETUP_L_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_IS_2K_L_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_SIGNED_BIN_N_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_N_C
+#define BN_MP_TOOM_MUL_C
+#define BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_PRIME_TAB_C
+#define BN_REVERSE_C
+#define BN_S_MP_ADD_C
+#define BN_S_MP_EXPTMOD_C
+#define BN_S_MP_MUL_DIGS_C
+#define BN_S_MP_MUL_HIGH_DIGS_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_SUB_C
+#define BNCORE_C
+#endif
+
+#if defined(BN_ERROR_C)
+   #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_MOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+   #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_ABS_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SET_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ABS_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_REDUCE_IS_2K_L_C
+   #define BN_S_MP_EXPTMOD_C
+   #define BN_MP_DR_IS_MODULUS_C
+   #define BN_MP_REDUCE_IS_2K_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_EXPTMOD_FAST_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_DR_SETUP_C
+   #define BN_MP_DR_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_C
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_NEG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+   #define BN_MP_RADIX_SIZE_C
+   #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ABS_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+   #define BN_MP_ERR_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+   #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ISODD_C
+   #define BN_FAST_MP_INVMOD_C
+   #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_SET_INT_C
+   #define BN_MP_MOD_C
+   #define BN_MP_GET_INT_C
+   #define BN_MP_SQRT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+   #define BN_MP_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SQR_C
+   #define BN_MP_SUB_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_GCD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+   #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_SET_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+   #define BN_MP_TOOM_MUL_C
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_S_MP_MUL_C
+   #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_GROW_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_EXPT_D_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+   #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_PRIME_IS_DIVISIBLE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SQRMOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+   #define BN_MP_PRIME_IS_PRIME_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_RADIX_SMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_MUL_HIGH_DIGS_C
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_MOD_2D_C
+   #define BN_S_MP_MUL_DIGS_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CMP_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_CLEAR_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_L_C)
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+   #define BN_MP_2EXPT_C
+   #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+   #define BN_MP_TOOM_SQR_C
+   #define BN_MP_KARATSUBA_SQR_C
+   #define BN_FAST_S_MP_SQR_C
+   #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+   #define BN_MP_N_ROOT_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_DIV_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_N_C)
+   #define BN_MP_SIGNED_BIN_SIZE_C
+   #define BN_MP_TO_SIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_N_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_L_C
+   #define BN_MP_REDUCE_2K_L_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SET_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include "tommath_superclass.h"
+#include "tommath_class.h"
+#else
+#define LTM_LAST
+#endif
+
+/* $Source: /cvs/libtom/libtommath/tommath_class.h,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/07/28 11:59:32 $ */
Added: sandbox/mp_math/libs/mp_math/tools/benchmark/tommath_superclass.h
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/tools/benchmark/tommath_superclass.h	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,81 @@
+// Copyright Kevin Sopp 2008.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+/* #define SC_RSA_1 */
+
+/* For reference.... On an Athlon64 optimizing for speed...
+
+   LTM's mpi.o with all functions [striped] is 142KiB in size.
+
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+   #define BN_MP_SHRINK_C
+   #define BN_MP_LCM_C
+   #define BN_MP_PRIME_RANDOM_EX_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_GCD_C
+   #define BN_MP_MOD_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_ADDMOD_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_SET_INT_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+   #define BN_REVERSE_C
+   #define BN_PRIME_TAB_C
+
+   /* other modifiers */
+   #define BN_MP_DIV_SMALL                    /* Slower division, not critical */
+
+   /* here we are on the last pass so we turn things off.  The functions classes are still there
+    * but we remove them specifically from the build.  This also invokes tweaks in functions
+    * like removing support for even moduli, etc...
+    */
+#ifdef LTM_LAST
+   #undef  BN_MP_TOOM_MUL_C
+   #undef  BN_MP_TOOM_SQR_C
+   #undef  BN_MP_KARATSUBA_MUL_C
+   #undef  BN_MP_KARATSUBA_SQR_C
+   #undef  BN_MP_REDUCE_C
+   #undef  BN_MP_REDUCE_SETUP_C
+   #undef  BN_MP_DR_IS_MODULUS_C
+   #undef  BN_MP_DR_SETUP_C
+   #undef  BN_MP_DR_REDUCE_C
+   #undef  BN_MP_REDUCE_IS_2K_C
+   #undef  BN_MP_REDUCE_2K_SETUP_C
+   #undef  BN_MP_REDUCE_2K_C
+   #undef  BN_S_MP_EXPTMOD_C
+   #undef  BN_MP_DIV_3_C
+   #undef  BN_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_MP_INVMOD_C
+
+   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 
+    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+    * trouble.  
+    */
+   #undef  BN_S_MP_MUL_DIGS_C
+   #undef  BN_S_MP_SQR_C
+   #undef  BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/tommath_superclass.h,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/14 13:29:17 $ */
Added: sandbox/mp_math/project-root.jam
==============================================================================
--- (empty file)
+++ sandbox/mp_math/project-root.jam	2008-10-24 14:49:35 EDT (Fri, 24 Oct 2008)
@@ -0,0 +1,53 @@
+#
+#   Copyright (c) 2006 João Abecasis
+#
+#   Distributed under the Boost Software License, Version 1.0. (See
+#   accompanying file LICENSE_1_0.txt or copy at
+#   http://www.boost.org/LICENSE_1_0.txt)
+#
+
+##
+##  IMPORTANT NOTE: This file MUST NOT be copied over a boost installation
+##
+
+path-constant top : . ;
+
+import modules ;
+import path ;
+
+local boost-root = [ modules.peek : BOOST_ROOT ] ;
+local math-header-include = $(top)/../.. ;
+
+if ! $(boost-root)
+{
+    local boost-search-dirs = [ modules.peek : BOOST_BUILD_PATH ] ;
+
+    for local dir in $(boost-search-dirs)
+    {
+        if [ path.glob $(dir)/../../../ : boost/version.hpp ]
+        {
+            boost-root += $(dir)/../../../ ;
+        }
+    }
+
+    if $(boost-root)
+    {
+        boost-root = [ path.make $(boost-root[1]) ] ;
+    }
+    else
+    {
+        ECHO "Warning: couldn't find BOOST_ROOT in" $(boost-root) ;
+    }
+}
+
+use-project /boost/unit_test : $(boost-root)/libs/test/build ;
+
+project
+    : requirements
+        <include>.
+        <include>$(boost-root)
+    :   #   build everything in ./bin.v2
+        build-dir bin.v2
+    ;
+
+path-constant BOOST_ROOT : $(boost-root) ;