Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r54213 - in sandbox/mp_math: boost/mp_math boost/mp_math/integer boost/mp_math/integer/detail boost/mp_math/integer/detail/asm boost/mp_math/integer/detail/base boost/mp_math/integer/detail/base/asm boost/mp_math/integer/detail/base/asm/asm boost/mp_math/integer/detail/base/asm/asm/x86 boost/mp_math/mp_int libs/mp_math libs/mp_math/examples libs/mp_math/test libs/mp_math/test/unbounded libs/mp_math/test/unbounded/signed libs/mp_math/test/unbounded/unsigned libs/mp_math/tools/benchmark
From: baraclese_at_[hidden]
Date: 2009-06-22 14:57:36


Author: baraclese
Date: 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
New Revision: 54213
URL: http://svn.boost.org/trac/boost/changeset/54213

Log:
* this is a complete rewrite which changes and renames the mp_int class template to integer
* the integer class template now acts as a frontend for different backends
* backends: GMP, libtommath and the native Boost one
* experimental code for unsigned unbounded integers, known to be broken
* increased test coverage
* moving away from the libtommath code for the native Boost implementation because it does not lend itself to assembly optimizations

Added:
   sandbox/mp_math/boost/mp_math/gmp.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/
      - copied from r54148, /sandbox/mp_math/boost/mp_math/mp_int/
   sandbox/mp_math/boost/mp_math/integer.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int.hpp
   sandbox/mp_math/boost/mp_math/integer/contexts.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/modpow_ctx.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/base/
   sandbox/mp_math/boost/mp_math/integer/detail/base/adder.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/asm/
   sandbox/mp_math/boost/mp_math/integer/detail/base/asm/asm/
      - copied from r54148, /sandbox/mp_math/boost/mp_math/mp_int/detail/asm/
   sandbox/mp_math/boost/mp_math/integer/detail/base/bitmanipulator.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/bitwise_ops.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/divider.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/from_integral.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/multiplier.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/primitive_ops.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/base/shifter.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/to_integral.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int_fwd.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int_integral.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint_fwd.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint_integral.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/divider.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/detail/div.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/gcd.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/jacobi.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/lcm.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/multiplier.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/mul.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/power.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/pow.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/root.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/root.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/string_conversion.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/unbounded_int_integral.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/unbounded_uint_integral.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/gmp_integer.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/integer.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp
   sandbox/mp_math/boost/mp_math/integer/integer_fwd.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/mp_int_fwd.hpp
   sandbox/mp_math/boost/mp_math/integer/libtom_integer.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/unbounded.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/unbounded_int.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/unbounded_traits.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int/traits.hpp
   sandbox/mp_math/boost/mp_math/integer/unbounded_uint.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer_serialization.hpp
      - copied, changed from r54148, /sandbox/mp_math/boost/mp_math/mp_int_serialization.hpp
   sandbox/mp_math/boost/mp_math/libtom.hpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/examples/
   sandbox/mp_math/libs/mp_math/examples/answer.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/examples/drops_in_the_ocean.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/examples/gmp.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/examples/jamfile.v2 (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/jamfile.v2 (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/abs.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/add.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/add.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/assign.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/bitmanipulation.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/bitmanipulation.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/bitwise_ops.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/bitwise_ops.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/bool_conversion.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/bool_conversion.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/cmp.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/cmp.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/ctors.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/ctors.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/div.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/div.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/gcd.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/gcd.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/integral_ops.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/integral_ops.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/jacobi.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/jacobi.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/jamfile.v2
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/jamfile.v2
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/lcm.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/lcm.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/modinv.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/modinv.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/modpow.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/modpow.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/mul.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/mul.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/numeric_limits.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/pow.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/pow.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/prerequisite.hpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/prerequisite.hpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/prime.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/prime.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/random.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/random.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/root.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/root.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/serialization.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/serialization.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/shift.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/shift.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/sqr.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/sqr.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/stream_io.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/stream_io.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/string_ops.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/string_ops.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/sub.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/sub.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/swap.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/to_integral.cpp
      - copied, changed from r54148, /sandbox/mp_math/libs/mp_math/test/to_integral.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/traits.cpp
      - copied unchanged from r54148, /sandbox/mp_math/libs/mp_math/test/traits.cpp
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/abs.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/add.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/bitmanipulation.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/bitwise_ops.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/bool_conversion.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/cmp.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/ctors.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/div.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/gcd.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/integral_ops.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/jacobi.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/jamfile.v2 (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/lcm.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/modinv.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/mul.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/numeric_limits.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/pow.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/prerequisite.hpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/root.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/serialization.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/shift.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/sqr.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/stream_io.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/string_ops.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/sub.cpp (contents, props changed)
   sandbox/mp_math/libs/mp_math/test/unbounded/unsigned/to_integral.cpp (contents, props changed)
Removed:
   sandbox/mp_math/boost/mp_math/integer/abs.hpp
   sandbox/mp_math/boost/mp_math/integer/add.hpp
   sandbox/mp_math/boost/mp_math/integer/ctors.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/asm/
   sandbox/mp_math/boost/mp_math/integer/detail/div.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/integral_ops.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/primitive_ops.hpp
   sandbox/mp_math/boost/mp_math/integer/detail/string_conversion_constants.hpp
   sandbox/mp_math/boost/mp_math/integer/div.hpp
   sandbox/mp_math/boost/mp_math/integer/gcd.hpp
   sandbox/mp_math/boost/mp_math/integer/jacobi.hpp
   sandbox/mp_math/boost/mp_math/integer/lcm.hpp
   sandbox/mp_math/boost/mp_math/integer/mod.hpp
   sandbox/mp_math/boost/mp_math/integer/modinv.hpp
   sandbox/mp_math/boost/mp_math/integer/modpow.hpp
   sandbox/mp_math/boost/mp_math/integer/modpow_ctx.hpp
   sandbox/mp_math/boost/mp_math/integer/mp_int.hpp
   sandbox/mp_math/boost/mp_math/integer/mp_int_fwd.hpp
   sandbox/mp_math/boost/mp_math/integer/mul.hpp
   sandbox/mp_math/boost/mp_math/integer/operators.hpp
   sandbox/mp_math/boost/mp_math/integer/pow.hpp
   sandbox/mp_math/boost/mp_math/integer/root.hpp
   sandbox/mp_math/boost/mp_math/integer/sqr.hpp
   sandbox/mp_math/boost/mp_math/integer/string_conversion.hpp
   sandbox/mp_math/boost/mp_math/integer/sub.hpp
   sandbox/mp_math/boost/mp_math/integer/traits.hpp
   sandbox/mp_math/boost/mp_math/mp_int/
   sandbox/mp_math/boost/mp_math/mp_int.hpp
   sandbox/mp_math/boost/mp_math/mp_int_serialization.hpp
   sandbox/mp_math/libs/mp_math/test/add.cpp
   sandbox/mp_math/libs/mp_math/test/bitmanipulation.cpp
   sandbox/mp_math/libs/mp_math/test/bitwise_ops.cpp
   sandbox/mp_math/libs/mp_math/test/bool_conversion.cpp
   sandbox/mp_math/libs/mp_math/test/cmp.cpp
   sandbox/mp_math/libs/mp_math/test/compile_all.cpp
   sandbox/mp_math/libs/mp_math/test/ctors.cpp
   sandbox/mp_math/libs/mp_math/test/div.cpp
   sandbox/mp_math/libs/mp_math/test/gcd.cpp
   sandbox/mp_math/libs/mp_math/test/integral_ops.cpp
   sandbox/mp_math/libs/mp_math/test/jacobi.cpp
   sandbox/mp_math/libs/mp_math/test/lcm.cpp
   sandbox/mp_math/libs/mp_math/test/modinv.cpp
   sandbox/mp_math/libs/mp_math/test/modpow.cpp
   sandbox/mp_math/libs/mp_math/test/mul.cpp
   sandbox/mp_math/libs/mp_math/test/pow.cpp
   sandbox/mp_math/libs/mp_math/test/prerequisite.hpp
   sandbox/mp_math/libs/mp_math/test/prime.cpp
   sandbox/mp_math/libs/mp_math/test/random.cpp
   sandbox/mp_math/libs/mp_math/test/root.cpp
   sandbox/mp_math/libs/mp_math/test/serialization.cpp
   sandbox/mp_math/libs/mp_math/test/shift.cpp
   sandbox/mp_math/libs/mp_math/test/sqr.cpp
   sandbox/mp_math/libs/mp_math/test/stream_io.cpp
   sandbox/mp_math/libs/mp_math/test/string_ops.cpp
   sandbox/mp_math/libs/mp_math/test/sub.cpp
   sandbox/mp_math/libs/mp_math/test/to_integral.cpp
   sandbox/mp_math/libs/mp_math/test/traits.cpp
Text files modified:
   sandbox/mp_math/boost/mp_math/integer.hpp | 21
   sandbox/mp_math/boost/mp_math/integer/contexts.hpp | 173 ---
   sandbox/mp_math/boost/mp_math/integer/detail/base/asm/asm/x86/gnu_386_primitive_ops.hpp | 31
   sandbox/mp_math/boost/mp_math/integer/detail/base/primitive_ops.hpp | 1971 ++++++++++++++++++++++++++++++++++++++-
   sandbox/mp_math/boost/mp_math/integer/detail/divider.hpp | 214 ++-
   sandbox/mp_math/boost/mp_math/integer/detail/gcd.hpp | 108 +
   sandbox/mp_math/boost/mp_math/integer/detail/jacobi.hpp | 37
   sandbox/mp_math/boost/mp_math/integer/detail/lcm.hpp | 68
   sandbox/mp_math/boost/mp_math/integer/detail/meta_math.hpp | 6
   sandbox/mp_math/boost/mp_math/integer/detail/modinv.hpp | 157 +-
   sandbox/mp_math/boost/mp_math/integer/detail/modpow.hpp | 421 ++++++-
   sandbox/mp_math/boost/mp_math/integer/detail/modular_reduction.hpp | 255 ++--
   sandbox/mp_math/boost/mp_math/integer/detail/multiplier.hpp | 859 ++++++++++++----
   sandbox/mp_math/boost/mp_math/integer/detail/power.hpp | 156 ++
   sandbox/mp_math/boost/mp_math/integer/detail/prime_tab.hpp | 6
   sandbox/mp_math/boost/mp_math/integer/detail/root.hpp | 301 +++--
   sandbox/mp_math/boost/mp_math/integer/detail/string_conversion.hpp | 1127 ++++++++++++++++++----
   sandbox/mp_math/boost/mp_math/integer/integer.hpp | 948 +-----------------
   sandbox/mp_math/boost/mp_math/integer/integer_fwd.hpp | 17
   sandbox/mp_math/boost/mp_math/integer/numeric_limits.hpp | 401 +++++++
   sandbox/mp_math/boost/mp_math/integer/unbounded_traits.hpp | 67
   sandbox/mp_math/boost/mp_math/integer_serialization.hpp | 64 +
   sandbox/mp_math/libs/mp_math/index.html | 2
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/add.cpp | 166 +-
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/bitmanipulation.cpp | 79
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/bitwise_ops.cpp | 94 +
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/bool_conversion.cpp | 43
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/cmp.cpp | 570 ++++++++++-
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/ctors.cpp | 277 +++-
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/div.cpp | 174 ++-
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/gcd.cpp | 56
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/integral_ops.cpp | 320 ++++--
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/jacobi.cpp | 26
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/jamfile.v2 | 15
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/lcm.cpp | 72
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/modinv.cpp | 26
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/modpow.cpp | 106 +-
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/mul.cpp | 83
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/pow.cpp | 76 +
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/prerequisite.hpp | 64
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/prime.cpp | 55
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/random.cpp | 49
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/root.cpp | 54
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/serialization.cpp | 30
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/shift.cpp | 36
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/sqr.cpp | 80 +
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/stream_io.cpp | 74
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/string_ops.cpp | 101 -
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/sub.cpp | 107 +-
   sandbox/mp_math/libs/mp_math/test/unbounded/signed/to_integral.cpp | 112 +-
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.cpp | 10
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_gmp.hpp | 43
   sandbox/mp_math/libs/mp_math/tools/benchmark/benchmark_mp_math.hpp | 23
   sandbox/mp_math/libs/mp_math/tools/benchmark/jamfile.v2 | 11
   sandbox/mp_math/libs/mp_math/tools/benchmark/main.cpp | 34
   sandbox/mp_math/libs/mp_math/tools/benchmark/modes.cpp | 96 +
   56 files changed, 7170 insertions(+), 3402 deletions(-)

Added: sandbox/mp_math/boost/mp_math/gmp.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/gmp.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,12 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_GMP_HPP
+#define BOOST_MP_MATH_GMP_HPP
+
+#include <boost/mp_math/integer/gmp_integer.hpp>
+
+#endif
+

Copied: sandbox/mp_math/boost/mp_math/integer.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,21 +1,16 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_HPP
-#define BOOST_MP_MATH_MP_INT_HPP
+#ifndef BOOST_MP_MATH_INTEGER_HPP
+#define BOOST_MP_MATH_INTEGER_HPP
 
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-#include <boost/mp_math/mp_int/mp_int.hpp>
+#include <boost/mp_math/integer/integer_fwd.hpp>
+#include <boost/mp_math/integer/integer.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/modinv.hpp>
-#include <boost/mp_math/mp_int/modpow.hpp>
-#include <boost/mp_math/mp_int/numeric_limits.hpp>
-#include <boost/mp_math/mp_int/prime.hpp>
-#include <boost/mp_math/mp_int/root.hpp>
+#include <boost/mp_math/integer/numeric_limits.hpp>
+#include <boost/mp_math/integer/prime.hpp>
+#include <boost/mp_math/integer/random.hpp>
 
 #endif

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/abs.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/abs.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,12 +0,0 @@
-// 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.set_sign(1);
- return tmp;
-}

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/add.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/add.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,83 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-template<class A, class T>
-void mp_int<A,T>::add_digit(digit_type b)
-{
- if (is_positive())
- {
- grow_capacity(size_ + 1);
- const digit_type carry =
- ops_type::add_single_digit(digits_, digits_, size_, b);
- if (carry)
- push(carry);
- }
- else
- {
- if (digits_[0] > b) // example: -16 + 5 = -11
- digits_[0] -= b;
- else
- {
- if (size_ == 1) // example: -1 + 5 = 4, or -5 + 5 = 0
- {
- digits_[0] = b - digits_[0];
- set_sign(1);
- }
- else // example -1000 + 5 = -995
- {
- ops_type::subtract_single_digit(digits_, digits_, size_, b);
- if (!digits_[size_-1])
- --size_;
- }
- }
- }
-}
-
-// 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 (size_ > rhs.size_)
- {
- x = this;
- y = &rhs;
- }
- else
- {
- x = &rhs;
- y = this;
- }
-
- grow_capacity(x->size_ + 1);
-
- digit_type carry = ops_type::add_digits(digits_,
- x->digits_,
- y->digits_, y->size_);
-
- size_type n = ops_type::ripple_carry(digits_ + y->size_,
- x->digits_ + y->size_,
- x->size_ - y->size_, carry);
- n += y->size_;
-
- if (n < x->size_) // this implies that there is no carry left
- {
- if (x != this)
- {
- std::memcpy(digits_ + n, x->digits_ + n, sizeof(digit_type) * (x->size_ - n));
- size_ = x->size_;
- }
- return;
- }
- else if (carry) // at this point n equals x->size_
- digits_[n++] = carry;
-
- size_ = n;
-}
-

Copied: sandbox/mp_math/boost/mp_math/integer/contexts.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/modpow_ctx.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/modpow_ctx.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/contexts.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,181 +1,18 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_MODPOW_CTX_HPP
-#define BOOST_MP_MATH_MP_INT_MODPOW_CTX_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#ifndef BOOST_MP_MATH_INTEGER_CONTEXTS_HPP
+#define BOOST_MP_MATH_INTEGER_CONTEXTS_HPP
 
 namespace boost {
 namespace mp_math {
 
 
-// r = x mod m given x and m
-template<class A, class T>
+template<class ApInt>
 struct modpow_ctx
-{
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::word_type word_type;
- typedef typename mp_int<A,T>::size_type size_type;
-
- // dr means diminished radix
- enum modulus_type_t
- { // R is our radix, i.e. digit_max
- mod_restricted_dr, // m = R**k - d; d <= R
- mod_unrestricted_dr, // m = 2**k - d; d <= R
- mod_unrestricted_dr_slow, // m = 2**k - d; d < d**(k/2)
- mod_odd,
- mod_generic
- }modulus_type;
-
- modpow_ctx() : precalculated(false){}
-
- modulus_type_t do_detect(const mp_int<A,T>& m) const;
-
- void detect_modulus_type(const mp_int<A,T>& m)
- {
- modulus_type = do_detect(m);
- }
-
- void precalculate(const mp_int<A,T>& m);
-
- mp_int<A,T> mu;
- digit_type rho;
- bool precalculated;
-};
-
-
-template<class A, class T>
-typename modpow_ctx<A,T>::modulus_type_t
-modpow_ctx<A,T>::do_detect(const mp_int<A,T>& m) const
-{
- if (m.size() == 1)
- return mod_unrestricted_dr;
-
- typename mp_int<A,T>::size_type count = 0;
-
- const int bits = m.precision() % mp_int<A,T>::valid_bits;
-
- if (!bits && m[m.size()-1] == mp_int<A,T>::digit_max)
- ++count;
-
- for (typename mp_int<A,T>::const_reverse_iterator d = m.rbegin() + 1;
- d != m.rend(); ++d)
- {
- if (*d != mp_int<A,T>::digit_max)
- break;
- else
- ++count;
- }
-
- // if all bits are set
- if (count == m.size() - 1)
- return mod_restricted_dr;
-
- // if all bits until the most significant digit are set
- if (count == m.size() - 2)
- {
- bool all_bits_set = true;
-
- // handle the remaining bits in the most significant digit
- typename mp_int<A,T>::digit_type mask = 1;
- for (int i = 0; i < bits; ++i)
- {
- if ((m[m.size()-1] & mask) == 0)
- {
- all_bits_set = false;
- break;
- }
- mask <<= 1;
- }
- if (all_bits_set)
- return mod_unrestricted_dr;
- }
-
- // if more than half of the bits are set
- if (count >= m.size() / 2)
- return mod_unrestricted_dr_slow;
-
- if (m.is_odd())
- return mod_odd;
-
- return mod_generic;
-}
-
-template<class A, class T>
-void modpow_ctx<A,T>::precalculate(const mp_int<A,T>& m)
-{
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::word_type word_type;
-
- switch (modulus_type)
- {
- case mod_restricted_dr:
- {
- rho = (word_type(1) << static_cast<word_type>(mp_int<A,T>::valid_bits))
- - static_cast<word_type>(m[0]);
- break;
- }
- case mod_unrestricted_dr:
- {
- const size_type p = m.precision();
-
- mp_int<A,T> tmp;
- tmp.pow2(p);
- tmp.sub_smaller_magnitude(m);
-
- rho = tmp[0];
- break;
- }
- case mod_unrestricted_dr_slow:
- {
- mp_int<A,T> tmp;
-
- tmp.pow2(m.precision());
- mu = tmp - m;
- break;
- }
- case mod_odd:
- {
- assert(m.is_odd());
-
- // 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 = m[0];
-
- static const typename mp_int<A,T>::size_type S =
- sizeof(digit_type) * std::numeric_limits<unsigned char>::digits;
-
- 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
- rho = (word_type(1) << (static_cast<word_type>(mp_int<A,T>::valid_bits))) - x;
- break;
- }
- case mod_generic:
- {
- // mu = b**2k/m
- mu.pow2(m.size() * 2 * mp_int<A,T>::digit_bits);
- mu /= m;
- break;
- }
- }
- precalculated = true;
-}
+{};
 
 
 } // namespace mp_math

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/ctors.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,272 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-template<class A, class T>
-mp_int<A,T>::mp_int()
-:
- digits_(0),
- size_(0),
- capacity_(0)
-{
-}
-
-template<class A, class T>
-mp_int<A,T>::mp_int(const allocator_type& a)
-:
- base_allocator_type(a),
- digits_(0),
- size_(0),
- capacity_(0)
-{
-}
-
-template<class A, class T>
-template<typename IntegralT>
-mp_int<A,T>::mp_int(
- IntegralT b,
- const allocator_type& a,
- typename enable_if<is_integral<IntegralT> >::type*)
-:
- base_allocator_type(a),
- digits_(0),
- size_(0),
- capacity_(0)
-{
- 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(size_ == 0);
-
- if (c == last)
- {
- set_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");
-
- set_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(size_ == 0);
-
- if (c == last)
- {
- set_sign(1);
- return;
- }
-
- if (*c == '-')
- {
- set_sign(-1);
- ++c;
- }
- else
- {
- if (f & std::ios_base::showpos)
- {
- if (*c == '+')
- ++c;
- else
- throw std::invalid_argument("mp_int<>::init: expected a '+' sign");
- }
- set_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,
- const allocator_type& a)
-:
- base_allocator_type(a),
- digits_(0),
- size_(0),
- capacity_(0)
-{
- init(first, last);
-}
-
-template<class A, class T>
-template<typename charT>
-mp_int<A,T>::mp_int(const charT* s, const allocator_type& a)
-:
- base_allocator_type(a),
- digits_(0),
- size_(0),
- capacity_(0)
-{
- init(s, s + std::char_traits<charT>::length(s));
-}
-
-template<class A, class T>
-template<typename charT>
-mp_int<A,T>::mp_int(const charT* s,
- std::ios_base::fmtflags f,
- const allocator_type& a)
-:
- base_allocator_type(a),
- digits_(0),
- size_(0),
- capacity_(0)
-{
- init(s, s + std::char_traits<charT>::length(s), f);
-}
-
-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,
- const allocator_type& a)
-:
- base_allocator_type(a),
- digits_(0),
- size_(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,
- const allocator_type& a)
-:
- base_allocator_type(a),
- digits_(0),
- size_(0),
- capacity_(0)
-{
- init(s.begin(), s.end(), f);
-}
-
-
-template<class A, class T>
-mp_int<A,T>::mp_int(const mp_int& copy)
-:
- base_allocator_type(copy.get_allocator())
-{
- digits_ = this->allocate(copy.size_);
- std::memcpy(digits_, copy.digits_, copy.size_ * sizeof(digit_type));
- size_ = copy.size_;
- set_capacity(copy.size_);
- set_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_),
- size_(copy.size_),
- capacity_(copy.capacity_) // this copies capacity and sign
-{
- copy.digits_ = 0;
- copy.size_ = 0;
- copy.capacity_ = 0;
-}
-#endif
-
-
-template<class A, class T>
-mp_int<A,T>::~mp_int()
-{
- if (digits_)
- this->deallocate(digits_, capacity());
-}
-

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/adder.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/adder.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,87 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_ADDER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_ADDER_HPP
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+
+template<class ApInt>
+struct adder
+{
+ typedef typename ApInt::traits_type traits_type;
+ typedef typename traits_type::digit_type digit_type;
+ typedef typename traits_type::size_type size_type;
+ typedef typename traits_type::ops_type ops_type;
+
+ static void add_smaller_magnitude(ApInt& z,
+ const ApInt& x, const ApInt& y);
+
+ static void subtract_smaller_magnitude(ApInt& z, const ApInt& x);
+ static void subtract_smaller_magnitude(ApInt& z,
+ const ApInt& x, const ApInt& y);
+};
+
+
+template<class ApInt>
+void adder<ApInt>::add_smaller_magnitude(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ assert(x.size() >= y.size());
+
+ digit_type carry = ops_type::add_digits(z.digits(),
+ x.digits(),
+ y.digits(), y.size());
+
+ size_type n = ops_type::ripple_carry(z.digits() + y.size(),
+ x.digits() + y.size(),
+ x.size() - y.size(), carry);
+ n += y.size();
+
+ if (n < x.size()) // this implies that there is no carry left
+ {
+ if (&x != &z)
+ {
+ std::memcpy(z.digits() + n,
+ x.digits() + n,
+ sizeof(digit_type) * (x.size() - n));
+ z.set_size(x.size());
+ }
+ return;
+ }
+ else if (carry) // at this point n equals x.size()
+ z[n++] = carry;
+
+ z.set_size(n);
+}
+
+template<class ApInt>
+void adder<ApInt>::subtract_smaller_magnitude(ApInt& z, const ApInt& x)
+{
+ ApInt::traits_type::ops_type::sub_smaller_magnitude(
+ z.digits(), z.digits(), z.size(), x.digits(), x.size());
+
+ z.clamp();
+}
+
+template<class ApInt>
+void adder<ApInt>::subtract_smaller_magnitude(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ ApInt::traits_type::ops_type::sub_smaller_magnitude(
+ z.digits(), x.digits(), x.size(), y.digits(), y.size());
+
+ z.clamp();
+}
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif

Modified: sandbox/mp_math/boost/mp_math/integer/detail/base/asm/asm/x86/gnu_386_primitive_ops.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/asm/x86/gnu_386_primitive_ops.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/asm/asm/x86/gnu_386_primitive_ops.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,25 +1,27 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-template
-struct primitive_ops<unsigned int, unsigned int, std::size_t>
+template<>
+struct primitive_ops<unsigned int, unsigned int, unsigned int>
+:
+ basic_primitive_ops<unsigned int,unsigned int,unsigned int>
 {
   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);
+ static unsigned int add_digits (dword* x, const dword* y, dword n);
+ static unsigned int subtract_digits(dword* x, const dword* y, dword n);
 };
 
 
-template
+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)
+primitive_ops<unsigned int, unsigned int, unsigned int>::
+add_digits(dword* x, const dword* y, dword n)
 {
- unsigned int carry = 0;
-
+ dword carry = 0;
+
   __asm__ __volatile__(
       "clc \n\t"
     "0: \n\t"
@@ -42,14 +44,13 @@
   return carry;
 }
 
-
-template
+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)
+primitive_ops<unsigned int, unsigned int, unsigned int>::
+subtract_digits(dword* x, const dword* y, dword n)
 {
- unsigned int carry = 0;
+ dword carry = 0;
 
   __asm__ __volatile__(
       "clc \n\t"

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/bitmanipulator.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/bitmanipulator.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,171 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_BITMANIPULATOR_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_BITMANIPULATOR_HPP
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+
+template<
+ class ApInt1,
+ class ApInt2,
+ int Cmp = ApInt1::traits_type::radix_bits < ApInt2::traits_type::radix_bits ? -1
+ : ApInt1::traits_type::radix_bits > ApInt2::traits_type::radix_bits ? : 1
+ : 0
+>
+struct bit_copier;
+
+
+template<class ApInt1, class ApInt2>
+struct bit_copier<ApInt1, ApInt2, -1>
+{
+ typedef typename ApInt1::size_type size_type1;
+ typedef typename ApInt2::size_type size_type2;
+ typedef typename ApInt1::digit_type digit_type1;
+ typedef typename ApInt2::digit_type digit_type2;
+
+ static const unsigned radix_bits1 = ApInt1::traits_type::radix_bits;
+ static const unsigned radix_bits2 = ApInt2::traits_type::radix_bits;
+
+ static void copy_bits(ApInt1& dst, size_type1 dst_offset,
+ const ApInt2& src, size_type2 src_offset, size_type1 n);
+};
+
+
+template<class ApInt1, class ApInt2>
+struct bit_copier<ApInt1, ApInt2, 1>
+{
+ typedef typename ApInt1::size_type size_type1;
+ typedef typename ApInt2::size_type size_type2;
+ typedef typename ApInt1::digit_type digit_type1;
+ typedef typename ApInt2::digit_type digit_type2;
+
+ static const unsigned radix_bits1 = ApInt1::traits_type::radix_bits;
+ static const unsigned radix_bits2 = ApInt2::traits_type::radix_bits;
+
+ static void copy_bits(ApInt1& dst, size_type1 dst_offset,
+ const ApInt2& src, size_type2 src_offset, size_type1 n);
+};
+
+
+template<class ApInt1, class ApInt2>
+struct bit_copier<ApInt1, ApInt2, 0>
+{
+ typedef typename ApInt1::size_type size_type1;
+ typedef typename ApInt2::size_type size_type2;
+ typedef typename ApInt1::digit_type digit_type1;
+ typedef typename ApInt2::digit_type digit_type2;
+
+ static const digit_type1 z1 = ~digit_type1(0);
+ static const digit_type2 z2 = ~digit_type2(0);
+ static const unsigned radix_bits = ApInt1::traits_type::radix_bits;
+
+ static void copy_bits(ApInt1& dst, size_type1 dst_offset,
+ const ApInt2& src, size_type2 src_offset, size_type1 n);
+};
+
+
+template<class ApInt1, class ApInt2>
+void bit_copier<ApInt1, ApInt2, 0>::copy_bits(
+ ApInt1& dst, size_type1 dst_offset,
+ const ApInt2& src, size_type2 src_offset, size_type1 num)
+{
+ if (!num)
+ return;
+
+ const size_type1 q1 = dst_offset / radix_bits;
+ const size_type1 r1 = dst_offset % radix_bits;
+ const size_type2 q2 = src_offset / radix_bits;
+ const size_type2 r2 = src_offset % radix_bits;
+
+ const digit_type1 r1_inv = radix_bits - r1;
+ const digit_type2 r2_inv = radix_bits - r2;
+
+ digit_type1* d = dst.digits() + q1;
+ const digit_type2* s = src.digits() + q2;
+
+ // If the offset into the first destination digit is not zero, i.e. r1 ==
+ // true, then we fill it up manually (normalize it) and then start the
+ // normalized copy loop.
+ if (!r1)
+ {
+ if (!r2)
+ {
+ const size_type1 num_digits = (num + (radix_bits - 1)) / radix_bits;
+ std::memcpy(d, s, num_digits * sizeof(digit_type2));
+ return;
+ }
+ else
+ goto normalized_bitcopy;
+ }
+ else
+ {
+ if (num < r1_inv)
+ {
+ *d &= (z1 >> r1_inv) | (z1 << (r1_inv + num));
+ *d |= ((*s >> r2) & ~(z2 << num)) << r1;
+ return;
+ }
+ else
+ {
+ *d &= ~(z1 << r1);
+
+ if (num < r2_inv)
+ {
+ *d |= ((*s >> r2) & ~(z2 << num)) << r1;
+ return;
+ }
+ else
+ {
+ *d |= (*s >> r2) << r1;
+ ++s;
+ num -= r2_inv;
+ *d |= (*s & ~(z2 << (radix_bits - num))) << (r1 + r2_inv);
+ goto normalized_bitcopy;
+ }
+ }
+ }
+
+normalized_bitcopy:
+
+ // fill one whole destination digit per iteration
+ while (num >= radix_bits)
+ {
+ *d = *s >> r2;
+ ++s;
+ *d |= *s << r2_inv;
+ ++d;
+ num -= radix_bits;
+ }
+
+ // copy remaining bits manually
+ if (num)
+ {
+ *d &= ~(z1 >> (radix_bits - num));
+
+ if (num < r2_inv)
+ *d |= (*s >> r2) & ~(z2 << num);
+ else
+ {
+ *d |= (*s >> r2);
+ ++s;
+ num -= r2;
+ *d |= (*s & (z2 >> (radix_bits - num))) << r2;
+ }
+ }
+}
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/bitwise_ops.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/bitwise_ops.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,148 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_BITWISE_OPS_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_BITWISE_OPS_HPP
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+
+template<class ApInt, bool IsSigned = ApInt::is_signed>
+struct bitwise_ops;
+
+
+template<class ApInt>
+struct bitwise_ops<ApInt,false>
+{
+ typedef typename ApInt::traits_type::digit_type digit_type;
+ typedef typename ApInt::traits_type::size_type size_type;
+
+ static void or_bits (ApInt& z, const ApInt& x, const ApInt& y);
+ static void and_bits(ApInt& z, const ApInt& x, const ApInt& y);
+ static void xor_bits(ApInt& z, const ApInt& x, const ApInt& y);
+ static void compl_bits(ApInt& z, const ApInt& x);
+};
+
+
+template<class ApInt>
+void
+bitwise_ops<ApInt,false>::or_bits(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ if (x.size() < y.size())
+ {
+ std::memcpy(z.digits() + x.size(),
+ y.digits() + x.size(),
+ (y.size() - x.size()) * sizeof(digit_type));
+ z.set_size(y.size());
+ }
+
+ for (size_type i = 0; i < std::min(x.size(), y.size()); ++i)
+ z[i] = x[i] | y[i];
+}
+
+template<class ApInt>
+void
+bitwise_ops<ApInt,false>::and_bits(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ const size_type m = std::min(x.size(), y.size());
+
+ for (size_type i = 0; i < m; ++i)
+ z[i] = z[i] & y[i];
+
+ z.set_size(m);
+ z.clamp();
+}
+
+template<class ApInt>
+void
+bitwise_ops<ApInt,false>::xor_bits(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ const size_type m = std::min(x.size(), y.size());
+
+ if (x.size() < y.size())
+ {
+ std::memcpy(z.digits() + x.size(),
+ y.digits() + x.size(),
+ (y.size() - x.size()) * sizeof(digit_type));
+ z.set_size(y.size());
+ }
+
+ for (size_type i = 0; i < m; ++i)
+ z[i] = x[i] ^ y[i];
+
+ z.clamp();
+}
+
+template<class ApInt>
+void
+bitwise_ops<ApInt,false>::compl_bits(ApInt& z, const ApInt& x)
+{
+ size_type i = 0;
+ for (; i < x.size() - 1; ++i)
+ z[i] = ~x[i];
+
+ unsigned count = 0;
+ digit_type bit = digit_type(1) << (ApInt::traits_type::radix_bits - 1);
+
+ if (x[i])
+ while (!(x[i] & bit))
+ {
+ bit >>= 1;
+ ++count;
+ if (count > 40)
+ break;
+ }
+ else
+ count = ApInt::traits_type::radix_bits - 1;
+
+ digit_type mask = ~digit_type(0);
+ mask >>= count;
+ z[i] = ~x[i] & mask;
+
+ z.set_size(x.size());
+ z.clamp_high_digit();
+}
+
+
+template<class ApInt>
+struct bitwise_ops<ApInt,true>
+{
+ static void or_bits (ApInt& z, const ApInt& x, const ApInt& y)
+ {
+ bitwise_ops<ApInt,false>::or_bits(z, x, y);
+ z.set_sign_bit(x.sign_bit() | y.sign_bit());
+ }
+
+ static void and_bits(ApInt& z, const ApInt& x, const ApInt& y)
+ {
+ bitwise_ops<ApInt,false>::and_bits(z, x, y);
+ z.set_sign_bit(x.sign_bit() & y.sign_bit());
+ }
+
+ static void xor_bits(ApInt& z, const ApInt& x, const ApInt& y)
+ {
+ bitwise_ops<ApInt,false>::xor_bits(z, x, y);
+ z.set_sign_bit(x.sign_bit() ^ y.sign_bit());
+ }
+
+ static void compl_bits(ApInt& z, const ApInt& x)
+ {
+ bitwise_ops<ApInt,false>::compl_bits(z, x);
+ z.set_sign_bit(z && x.is_positive() ? 1 : 0);
+ }
+};
+
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/divider.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/divider.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,105 @@
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_DIVIDER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_DIVIDER_HPP
+
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+
+template<class ApInt>
+struct divider
+{
+ typedef typename ApInt::traits_type traits_type;
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::size_type size_type;
+
+ // z = z % 2^n
+ static void modulo_pow2(ApInt& z, size_type n);
+ static void divide_by_2(ApInt& z);
+ static void divide_by_3(ApInt& z);
+};
+
+
+template<class ApInt>
+void divider<ApInt>::modulo_pow2(ApInt& z, size_type n)
+{
+ // if modulus >= z then return
+ if (n >= z.size() * traits_type::radix_bits)
+ return;
+
+ // clear high bits
+ const digit_type mask =
+ (1 << (static_cast<digit_type>(n % traits_type::radix_bits))) - 1;
+
+ z[n / traits_type::radix_bits] &= mask;
+
+ z.set_size(n / traits_type::radix_bits + 1);
+ // TODO was z.clamp() hope it is correct now with the +1! check again!
+
+ z.clamp();
+ // TODO if (!z) z.set_sign_bit(0) is necessary here
+}
+
+template<class ApInt>
+inline void divider<ApInt>::divide_by_2(ApInt& z)
+{
+ traits_type::ops_type::divide_by_two(z.digits(), z.digits(), z.size());
+
+ z.clamp_high_digit();
+}
+
+// divide by three (based on routine from MPI and the GMP manual)
+template<class ApInt>
+inline void divider<ApInt>::divide_by_3(ApInt& z)
+{
+ typedef typename traits_type::word_type word_type;
+
+ // b = 2^radix_bits / 3
+ static const word_type b = (word_type(1) << traits_type::radix_bits) / 3;
+
+ word_type w = 0;
+ for (typename ApInt::reverse_iterator d = z.rbegin(); d != z.rend(); ++d)
+ {
+ w = (w << static_cast<word_type>(traits_type::radix_bits))
+ | static_cast<word_type>(*d);
+
+ word_type t;
+ if (w >= 3U)
+ {
+ // multiply w by [1/3]
+ t = (w * b) >> static_cast<word_type>(traits_type::radix_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 >= 3U)
+ {
+ t += 1;
+ w -= 3;
+ }
+ }
+ else
+ t = 0;
+
+ *d = static_cast<digit_type>(t);
+ }
+
+ z.clamp(); // TODO clamp_high_digit should suffice
+}
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/from_integral.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/from_integral.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,191 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_FROM_INTEGRAL_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_FROM_INTEGRAL_HPP
+
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+
+template<
+ class ApInt,
+ typename IntegralT,
+ bool ApIntIsSigned = ApInt::is_signed,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed,
+ bool fits_into_digit_type =
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<typename ApInt::digit_type>::digits
+ // TODO shouldn't we cmp against signed digit_type for signed integral types?
+>
+struct from_integral_converter;
+
+
+// Specializations for unsigned ApInts //
+/////////////////////////////////////////
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, false, false, true>
+{
+ static void convert(ApInt& z, IntegralT x)
+ {
+ z[0] = x;
+ z.set_size(1);
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, false, true, true>
+{
+ static void convert(ApInt& z, IntegralT x)
+ {
+ if (x >= 0)
+ {
+ z[0] = static_cast<typename ApInt::digit_type>(x);
+ z.set_size(1);
+ }
+ else
+ throw std::domain_error("from_integral_converter::convert: "
+ "cannot convert negative integral value to unsigned integer value");
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, false, false, false>
+{
+ static void convert(ApInt& z, IntegralT x);
+};
+
+
+template<class ApInt, typename IntegralT>
+void from_integral_converter<ApInt, IntegralT, false, false, false>::
+convert(ApInt& z, IntegralT x)
+{
+ static const IntegralT mask = ~(~IntegralT(0) << ApInt::traits_type::radix_bits);
+
+ if (x == 0)
+ {
+ z[0] = 0;
+ z.set_size(1);
+ return;
+ }
+
+ typename ApInt::iterator z_iter = z.begin();
+ while (x)
+ {
+ *z_iter++ = static_cast<typename ApInt::digit_type>(x & mask);
+ x >>= ApInt::traits_type::radix_bits;
+ }
+
+ z.set_size(z_iter - z.begin());
+}
+
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, false, true, false>
+{
+ typedef typename make_unsigned<IntegralT>::type unsigned_integral_type;
+
+ static void convert(ApInt& z, IntegralT x)
+ {
+ if (x >= 0)
+ from_integral_converter<
+ ApInt, unsigned_integral_type
+ >::convert(z, static_cast<unsigned_integral_type>(x));
+ else
+ throw std::domain_error("from_integral_converter::convert: "
+ "cannot convert negative integral value to unsigned integer value");
+ }
+};
+
+
+// Specializations for signed ApInts //
+///////////////////////////////////////
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, true, false, true>
+{
+ static void convert(ApInt& z, IntegralT x)
+ {
+ z[0] = x;
+ z.set_size(1);
+ z.set_sign_bit(1);
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, true, true, true>
+{
+ static void convert(ApInt& z, IntegralT x)
+ {
+ if (x >= 0)
+ {
+ z[0] = static_cast<typename ApInt::digit_type>(x);
+ z.set_sign_bit(0);
+ }
+ else
+ {
+ z[0] = static_cast<typename ApInt::digit_type>(-x);
+ z.set_sign_bit(1);
+ }
+ z.set_size(1);
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, true, false, false>
+{
+ static void convert(ApInt& z, IntegralT x)
+ {
+ from_integral_converter<ApInt, IntegralT, false, false, false>::
+ convert(z, x);
+ z.set_sign_bit(0);
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct from_integral_converter<ApInt, IntegralT, true, true, false>
+{
+ typedef typename make_unsigned<IntegralT>::type unsigned_integral_type;
+
+ static void convert(ApInt& z, IntegralT x)
+ {
+ if (x >= 0)
+ {
+ from_integral_converter<
+ ApInt, unsigned_integral_type, false, true, false
+ >::convert(z, static_cast<unsigned_integral_type>(x));
+ z.set_sign_bit(0);
+ }
+ else
+ {
+ from_integral_converter<
+ ApInt, IntegralT, false, true, false
+ >::convert(z, static_cast<unsigned_integral_type>(-x));
+ z.set_sign_bit(1);
+ }
+ }
+};
+
+
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/multiplier.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/multiplier.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,108 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_MULTIPLIER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_MULTIPLIER_HPP
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+
+template<class ApInt>
+struct multiplier
+{
+ typedef ApInt int_type;
+ typedef typename int_type::digit_type digit_type;
+ typedef typename int_type::traits_type traits_type;
+ typedef typename traits_type::ops_type ops_type;
+
+ static void multiply_or_square(ApInt& z, const ApInt& x, const ApInt& y);
+
+ static void mul (ApInt& z, const ApInt& x, const ApInt& y);
+ static void comba_mul(ApInt& z, const ApInt& x, const ApInt& y);
+
+ static void comba_sqr(ApInt& z, const ApInt& x);
+};
+
+
+template<class ApInt>
+void
+multiplier<ApInt>::multiply_or_square(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ if (&x == &y)
+ comba_sqr(z, x);
+ else
+ mul(z, x, y);
+}
+
+template<class ApInt>
+void multiplier<ApInt>::mul(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ // always multiply larger by smaller number
+ const ApInt* a = &x;
+ const ApInt* b = &y;
+ if (a->size() < b->size())
+ std::swap(a, b);
+
+ if (b->size() == 1U)
+ {
+ if ((*b)[0] == 0U)
+ {
+ z[0] = 0;
+ z.set_size(1);
+ // TODO set_sign_bit(0) for signed ApInt!
+ return;
+ }
+ else if ((*b)[0] == 1U)
+ {
+ z = *a;
+ return;
+ }
+
+ ApInt::template integral_ops<digit_type>::multiply(z, *a, (*b)[0]);
+
+ return;
+ }
+
+ comba_mul(z, *a, *b);
+}
+
+template<class ApInt>
+void multiplier<ApInt>::comba_mul(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ // We assert this because otherwise we would need to call z.clamp() below.
+ assert(x);
+ assert(y);
+
+ if (x.size() == y.size())
+ ops_type::comba_mul(z.digits(), x.digits(), y.digits(), y.size());
+ else
+ ops_type::comba_mul(z.digits(), x.digits(), x.size(),
+ y.digits(), y.size());
+
+ z.set_size(x.size() + y.size());
+ z.clamp_high_digit();
+}
+
+template<class ApInt>
+void multiplier<ApInt>::comba_sqr(ApInt& z, const ApInt& x)
+{
+ ops_type::comba_sqr(z.digits(), x.digits(), x.size());
+
+ z.set_size(x.size() + x.size());
+
+ z.clamp_high_digit();
+}
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Copied: sandbox/mp_math/boost/mp_math/integer/detail/base/primitive_ops.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/primitive_ops.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,19 +1,27 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_DETAIL_PRIMITIVE_OPS
-#define BOOST_MP_MATH_MP_INT_DETAIL_PRIMITIVE_OPS
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_PRIMITIVE_OPS
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_PRIMITIVE_OPS
+
+#include <cassert>
+#include <cstring>
+#include <algorithm>
+#include <boost/cstdint.hpp>
+#include <iostream>
 
 namespace boost {
 namespace mp_math {
 namespace detail {
+namespace base {
 
 
 // this struct contains some basic arithmetic algorithms
 // which can be implemented via assembly rather easily
 
+#ifdef BOOST_MP_MATH_PRIMITIVE_OPS_OLD
 template<typename DigitT, typename WordT, typename SizeT>
 struct basic_primitive_ops
 {
@@ -24,6 +32,15 @@
   static const word_type digit_bits = std::numeric_limits<digit_type>::digits;
 
   // ADD ------------------------------------
+ // z = x + y, returns carry
+ static digit_type add(digit_type& z, digit_type x, digit_type y);
+ // z += x, returns carry
+ static digit_type add(digit_type& z, digit_type x);
+ // z += x * y, returns carry
+ static digit_type multiply_add(digit_type& z_hi, digit_type& z_lo,
+ digit_type x, digit_type y);
+ // z = x * y, returns high part of the product
+ static digit_type mul(digit_type& z, digit_type x, digit_type y);
 
   // add y to the digits in x and store result in z
   // xlen must be > 0
@@ -102,6 +119,24 @@
                         const digit_type* x,
                         const digit_type* y, size_type xylen);
 
+ // z = x * y; precondition: xlen >= ylen and workspace must have at least ylen
+ // digits this function is only used by the integral ops interaction code, it
+ // allows x and z to be the same pointer.
+ static void comba_mul(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ digit_type* workspace);
+
+ // computes the lower num digits of the product of x and y
+ static void comba_mul_lo(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num);
+
+ // computes the high product of x and y without num least significant digits
+ // basically the result is: z = (x*y) >> radix^num
+ static void comba_mul_hi(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num);
+
   // SQR ------------------------------------
 
   // z = x * x;
@@ -109,11 +144,10 @@
 
   // MADD ------------------------------------
 
- // z = w * x + y
+ // z = z + x * y
   static digit_type multiply_add_digits(digit_type* z,
- const digit_type* w,
- digit_type x,
- const digit_type* y,
+ const digit_type* x,
+ digit_type y,
                                         size_type n);
 
   // DIV -------------------------------------
@@ -126,12 +160,109 @@
   static digit_type divide_by_digit(digit_type* z,
                                     const digit_type* x, size_type xlen,
                                     digit_type y);
+
+ // q = x/y, r = x%y; workspace must have length of ylen + 1
+ static void divide(digit_type* q, digit_type* r,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ digit_type* workspace);
+
+ // SHIFT -----------------------------------
+
+ // shifts x by n bits to the left, where n > 0 && n < digit_bits
+ // returns carry
+ static digit_type shift_bits_left(digit_type* x, size_type xlen, size_type n);
+
+ // shifts x by n bits to the right, where n > 0 && n < digit_bits
+ static void shift_bits_right(digit_type* x, size_type xlen, size_type n);
+
+ // CMP -------------------------------------
+
+ // returns 1 if x > y
+ // returns 0 if x == y
+ // returns -1 if x < y
+ static int compare_magnitude(const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen);
 };
 
 
 
 template<typename D, typename W, typename S>
 inline
+D basic_primitive_ops<D,W,S>::add(digit_type& z, digit_type x, digit_type y)
+{
+ z = x + y;
+ return z < x;
+}
+
+template<typename D, typename W, typename S>
+inline
+D basic_primitive_ops<D,W,S>::add(digit_type& z, digit_type x)
+{
+ z += x;
+ return z < x;
+}
+
+template<typename D, typename W, typename S>
+inline
+D basic_primitive_ops<D,W,S>::multiply_add(digit_type& z_hi, digit_type& z_lo,
+ digit_type x, digit_type y)
+{
+ static const digit_type lo_mask = (1 << digit_bits / 2) - 1;
+
+ const digit_type x_lo = x & lo_mask;
+ const digit_type x_hi = x >> digit_bits/2;
+ const digit_type y_lo = y & lo_mask;
+ const digit_type y_hi = y >> digit_bits/2;
+
+ const digit_type z0 = x_lo * y_lo;
+ const digit_type z1 = x_lo * y_hi;
+ const digit_type z2 = x_hi * y_lo;
+ const digit_type z3 = x_hi * y_hi;
+
+ digit_type z12 = z1 + (z0 >> digit_bits/2);
+ const digit_type carry = add(z12, z2);
+
+ const digit_type w_lo = (z12 << digit_bits/2) + (z0 & lo_mask);
+ const digit_type w_hi = z3 + (carry << digit_bits/2) + (z12 >> digit_bits/2);
+
+ digit_type u = add(z_lo, w_lo);
+ digit_type v = add(z_hi, u);
+
+ return v + add(z_hi, w_hi);
+}
+
+template<typename D, typename W, typename S>
+inline
+D basic_primitive_ops<D,W,S>::mul(digit_type& z_lo, digit_type x, digit_type y)
+{
+ static const digit_type lo_mask = (1 << digit_bits / 2) - 1;
+ static const digit_type hi_mask = lo_mask << (digit_bits / 2);
+
+ const digit_type x_lo = x & lo_mask;
+ const digit_type x_hi = x & hi_mask;
+ const digit_type y_lo = y & lo_mask;
+ const digit_type y_hi = y & hi_mask;
+
+ // do a normal school multiplication on the 'half digits'
+ const digit_type z0 = x_lo * y_lo;
+ const digit_type z1 = x_lo * y_hi;
+ const digit_type z2 = x_hi * y_lo;
+ const digit_type z3 = x_hi * y_hi;
+
+ digit_type z12 = z1 + (z0 & hi_mask);
+ const digit_type carry = add(z12, z2);
+
+ z_lo = (z12 << digit_bits/2) | (z0 & lo_mask);
+
+ const digit_type z_hi = z3 + (carry << digit_bits/2) + (z12 & hi_mask);
+
+ return z_hi;
+}
+
+//////////////////////////////////////////////////////////////
+template<typename D, typename W, typename S>
+inline
 D basic_primitive_ops<D,W,S>::add_single_digit(digit_type* z,
                                                const digit_type* x,
                                                size_type xlen,
@@ -397,58 +528,67 @@
 {
   assert(xlen >= ylen);
 
- word_type acc = 0; // accumulator for each column
- word_type carry = 0;
+ // instead of initializing acc and carry with zero and entering the loop below
+ // we manually calculate the first low digit of the result here
+ // acc is the accumulator for each column
+ word_type acc = static_cast<word_type>(*x) * static_cast<word_type>(*y++);
+ word_type 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 1
- for (size_type i = 0; i < ylen; ++i)
+ for (size_type i = 1; i < ylen; ++i)
   {
- const digit_type* a = x;
- const digit_type* b = y + i;
-
     for (size_type j = 0; j <= i; ++j)
     {
- acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ acc += static_cast<word_type>(*x++) * static_cast<word_type>(*y--);
       carry += acc >> digit_bits;
       acc = static_cast<digit_type>(acc);
     }
 
+ x -= i + 1;
+ y += i + 2;
     *z++ = static_cast<digit_type>(acc);
     acc = static_cast<digit_type>(carry);
     carry >>= digit_bits;
   }
 
   // phase 2
+ --y; // now y is at index ylen - 1
   for (size_type i = 0; i < xlen - ylen; ++i)
   {
- const digit_type* a = x + ylen + i;
- const digit_type* b = y;
+ ++x;
 
     for (size_type j = 0; j < ylen; ++j)
     {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
+ acc += static_cast<word_type>(*x++) * static_cast<word_type>(*y--);
       carry += acc >> digit_bits;
       acc = static_cast<digit_type>(acc);
     }
 
+ x -= ylen;
+ y += ylen;
     *z++ = static_cast<digit_type>(acc);
- acc = static_cast<digit_type>(carry);
+ acc = static_cast<digit_type>(carry);
     carry >>= digit_bits;
   }
 
   // phase 3
   for (size_type i = 0; i < ylen - 1; ++i)
   {
- const digit_type* a = x + xlen - 1;
- const digit_type* b = y + i + 1;
+ ++x;
 
     for (size_type j = i + 1; j < ylen; ++j)
     {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
+ acc += static_cast<word_type>(*x++) * static_cast<word_type>(*y--);
       carry += acc >> digit_bits;
       acc = static_cast<digit_type>(acc);
     }
 
+ x -= ylen - 1 - i;
+ y += ylen - 1 - i;
     *z++ = static_cast<digit_type>(acc);
     acc = static_cast<digit_type>(carry);
     carry >>= digit_bits;
@@ -463,11 +603,68 @@
                                       const digit_type* x,
                                       const digit_type* y, size_type xylen)
 {
+ // phase 1
+ // instead of initializing acc and carry with zero and entering the loop below
+ // we manually calculate the first low digit of the result here
+ word_type acc = static_cast<word_type>(*x) * static_cast<word_type>(*y++);
+ word_type 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;
+
+ for (size_type i = 1; i < xylen; ++i)
+ {
+ for (size_type j = 0; j <= i; ++j)
+ {
+ acc += static_cast<word_type>(*x++) * static_cast<word_type>(*y--);
+ carry += acc >> digit_bits;
+ acc = static_cast<digit_type>(acc);
+ }
+
+ x -= i + 1;
+ y += i + 2;
+ *z++ = static_cast<digit_type>(acc);
+ acc = static_cast<digit_type>(carry);
+ carry >>= digit_bits;
+ }
+ --y;
+ // phase 2
+ while (--xylen)
+ {
+ ++x;
+ for (size_type j = 0; j < xylen; ++j)
+ {
+ acc += static_cast<word_type>(*x++) * static_cast<word_type>(*y--);
+ carry += acc >> digit_bits;
+ acc = static_cast<digit_type>(acc);
+ }
+
+ x -= xylen;
+ y += xylen;
+ *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, size_type xlen,
+ const digit_type* y, size_type ylen,
+ digit_type* workspace)
+{
+ assert(xlen >= ylen);
+
+ digit_type* w = workspace;
   word_type acc = 0; // accumulator for each column
   word_type carry = 0;
 
   // phase 1
- for (size_type i = 0; i < xylen; ++i)
+ for (size_type i = 0; i < ylen; ++i)
   {
     const digit_type* a = x;
     const digit_type* b = y + i;
@@ -479,29 +676,231 @@
       acc = static_cast<digit_type>(acc);
     }
 
- *z++ = static_cast<digit_type>(acc);
- acc = static_cast<digit_type>(carry);
+ *w++ = static_cast<digit_type>(acc);
+ acc = static_cast<digit_type>(carry);
     carry >>= digit_bits;
   }
 
+ w -= ylen;
+
   // phase 2
- for (size_type i = 1; i < xylen; ++i)
+ for (size_type i = 0; i < xlen - ylen; ++i)
   {
- const digit_type* a = y + xylen - 1;
- const digit_type* b = x + i;
+ const digit_type* a = x + 1 + i;
+ const digit_type* b = y + ylen - 1;
 
- for (size_type j = 0; j < xylen - i; ++j)
+ for (size_type j = 0; j < ylen; ++j)
     {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
       carry += acc >> digit_bits;
       acc = static_cast<digit_type>(acc);
     }
 
- *z++ = static_cast<digit_type>(acc);
- acc = static_cast<digit_type>(carry);
+ *z++ = *w;
+ *w++ = static_cast<digit_type>(acc);
+
+ if (static_cast<size_type>(w - workspace) == ylen)
+ w -= ylen;
+
+ acc = static_cast<digit_type>(carry);
+ carry >>= digit_bits;
+ }
+
+ // phase 3
+ for (size_type i = 0; i < ylen - 1; ++i)
+ {
+ const digit_type* a = x + xlen - (ylen - 1);
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = i + 1; j < ylen; ++j)
+ {
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ carry += acc >> digit_bits;
+ acc = static_cast<digit_type>(acc);
+ }
+
+ *z++ = *w;
+ *w++ = static_cast<digit_type>(acc);
+
+ if (static_cast<size_type>(w - workspace) == ylen)
+ w -= ylen;
+
+ acc = static_cast<digit_type>(carry);
     carry >>= digit_bits;
   }
 
+ const digit_type* ws_index = w;
+
+ while (w < (workspace + ylen))
+ *z++ = *w++;
+
+ w = workspace;
+
+ while (w < ws_index)
+ *z++ = *w++;
+
+ *z = static_cast<digit_type>(acc);
+}
+
+template<typename D, typename W, typename S>
+void
+basic_primitive_ops<D,W,S>::comba_mul_lo(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num)
+{
+ //assert(xlen >= ylen);
+ assert(num <= (xlen + ylen));
+
+ word_type acc = 0; // accumulator for each column
+ word_type carry = 0;
+
+ // phase 1
+ if (num)
+ {
+ const size_type m = ylen < num ? ylen : num;
+ for (size_type i = 0; i < m; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = y + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ 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
+ if (num >= ylen)
+ {
+ const size_type m = xlen - ylen < num ? xlen - ylen : num;
+ for (size_type i = 0; i < m; ++i)
+ {
+ const digit_type* a = x + 1 + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = 0; j < ylen; ++j)
+ {
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ 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 3
+ if (num >= xlen + ylen)
+ {
+ const size_type m = ylen - 1 < num ? ylen - 1 : num;
+ for (size_type i = 0; i < m; ++i)
+ {
+ const digit_type* a = x + xlen - (ylen - 1);
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = i + 1; j < ylen; ++j)
+ {
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ 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_hi(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num)
+{
+ //assert(xlen >= ylen);
+ assert(num > 0);
+ assert(num < (xlen + ylen));
+
+ word_type acc = 0; // accumulator for each column
+ word_type carry = 0;
+
+ // phase 1
+ if (num < ylen)
+ {
+ for (size_type i = num; i < ylen; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = y + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ 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
+ if (num < xlen)
+ {
+ for (size_type i = num - ylen; i < xlen - ylen; ++i)
+ {
+ const digit_type* a = x + 1 + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = 0; j < ylen; ++j)
+ {
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ 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 3
+ if (num < (xlen + ylen))
+ {
+ for (size_type i = num - (xlen + ylen); i < ylen - 1; ++i)
+ {
+ const digit_type* a = x + xlen - (ylen - 1);
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = i + 1; j < ylen; ++j)
+ {
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
+ 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);
 }
 
@@ -558,7 +957,6 @@
 
   *z = static_cast<digit_type>(acc);*/
 
-
   word_type acc = 0; // accumulator for each column
   word_type carry = 0;
 
@@ -583,12 +981,12 @@
   // phase 2
   for (size_type i = 1; i < xlen; ++i)
   {
- const digit_type* a = x + xlen - 1;
- const digit_type* b = x + i;
+ const digit_type* a = x + i;
+ const digit_type* b = x + xlen - 1;
 
     for (size_type j = 0; j < xlen - i; ++j)
     {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
+ acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
       carry += acc >> digit_bits;
       acc = static_cast<digit_type>(acc);
     }
@@ -603,24 +1001,25 @@
 
 template<typename D, typename W, typename S>
 D basic_primitive_ops<D,W,S>::multiply_add_digits(digit_type* z,
- const digit_type* w,
- digit_type x,
- const digit_type* y,
+ const digit_type* x,
+ digit_type y,
                                                   size_type n)
 {
- word_type carry = 0;
+ digit_type carry = 0;
   while (n--)
   {
- const word_type r = static_cast<word_type>(*w++)
- * static_cast<word_type>(x)
- + static_cast<word_type>(*y++)
- + carry;
-
- *z++ = static_cast<digit_type>(r);
- carry = r >> digit_bits;
+ const word_type r = static_cast<word_type>(*z)
+ + static_cast<word_type>(*x)
+ * static_cast<word_type>(y)
+ + static_cast<word_type>(carry);
+
+ *z = static_cast<digit_type>(r);
+ carry = static_cast<digit_type>(r >> digit_bits);
+ ++z;
+ ++x;
   }
 
- return static_cast<digit_type>(carry);
+ return carry;
 }
 
 
@@ -644,12 +1043,68 @@
     carry = r;
   }
 }
+/*
+// divides half digits [x1, x2, x3] by [y1, y2] and returns remainder
+template<typename D, typename W, typename S>
+D basic_primitive_ops<D,W,S>::divide_half_digits(
+ digit_type& q,
+ digit_type x12, digit_type x3,
+ digit_type y1, digit_type y2)
+{
+ q = x12 / y1;
+ const digit_type c = x12 - q * y1;
+ const digit_type D = q * y2;
+
+ digit_type R = (c << digit_bits / 2) | x3;
+
+ if (R < D) // R is too large by at most 2
+ {
+ const digit_type y = (y1 << digit_bits / 2) | y2;
+ --q;
+ R += y;
+ if (R < D)
+ {
+ --q;
+ R += y;
+ }
+ }
+
+ return R - D;
+}
+
+// divide two digit number x by one digit number y
+// returns remainder
+// q = x / y , r = x % y
+template<typename D, typename W, typename S>
+D basic_primitive_ops<D,W,S>::divide(digit_type& q,
+ digit_type x_hi, digit_type x_lo,
+ digit_type y)
+{
+ static const digit_type lo_mask = (1 << digit_bits / 2) - 1;
+ static const digit_type hi_mask = lo_mask << (digit_bits / 2);
+
+ digit_type q1, q2;
+ const digit_type r = divide_half_digits(q1, x_hi, x_lo & hi_mask,
+ y & hi_mask, y & lo_mask);
+ const digit_type s = divide_half_digits(q2, r, x_lo & lo_mask,
+ y & hi_mask, y & lo_mask);
+ q = (q1 << digit_bits / 2) & q2;
+ return s;
+}*/
 
 template<typename D, typename W, typename S>
 D basic_primitive_ops<D,W,S>::divide_by_digit(digit_type* z,
                                               const digit_type* x, size_type n,
                                               digit_type y)
 {
+/* z += n - 1;
+ x += n - 1;
+
+ while (n--)
+ {
+ if ()
+ }*/
+
   z += n - 1;
   x += n - 1;
 
@@ -658,47 +1113,1427 @@
   while (n--)
   {
     w = (w << digit_bits) | static_cast<word_type>(*x--);
- digit_type tmp;
+ //this turned out to be slower:
+ //const digit_type q = static_cast<digit_type>(w / y);
+ //w -= q * y;
+ //*z-- = q;
+ digit_type q;
     if (w >= y)
     {
- tmp = static_cast<digit_type>(w / y);
- w -= tmp * y;
+ q = static_cast<digit_type>(w / y);
+ w -= q * y;
     }
     else
- tmp = 0;
- *z-- = tmp;
+ q = 0;
+ *z-- = q;
   }
 
   return static_cast<digit_type>(w);
 }
 
+// This is basically a Knuth division with the difference that we form the trial
+// quotient by using a 3 digit by 2 digit division instead of a 2 by 1. This has
+// the effect of limiting the error in q_hat to 1 instead of 2.
+/*template<typename D, typename W, typename S>
+void basic_primitive_ops<D,W,S>::divide(digit_type* q, digit_type* r,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ digit_type* ws)
+{
+ assert(xlen >= 3);
+ assert(ylen >= 2);
 
+ if (y[ylen-1] & (1 << (digit_bits-1))) // if y is already normalized
+ {
+ digit_type q_estimate =
+ div3by2(x[xlen - 1], x[xlen - 2], x[xlen - 3],
+ y[ylen - 1], y[ylen - 2]);
+
+ // multiply subtract in place
+ digit_type* ws_ptr = ws;
+ digit_type borrow = 0;
+ for (size_type i = 0; i < ylen; ++i)
+ {
+ const word_type tmp = static_cast<word_type>(*y++)
+ * static_cast<word_type>(q_estimate);
+ *ws_ptr++ = x_ptr - static_cast<digit_type>(tmp);
+ borrow = static_cast<digit_type>(tmp >> digit_bits);
+ }
 
+ return borrow;
+ }
+ else
+ {
+ //count leading zero bits
+ norm = 1;
 
-// 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>
-{};
+ // store normalized y at ws[0] and normalized x at ws[ylen]
+ digit_type q_estimate =
+ div3by2(ws[xlen - 1], ws[xlen - 2], ws[xlen - 3],
+ ws[ylen - 1], ws[ylen - 2]);
+ }
 
 
-// Here we include primitive_ops specializations that use assembler
+ // TODO normalize in place or store normalized y at ws and let wslen be
+ // ylen * 2 + 1.
 
-#if defined(BOOST_MP_MATH_MP_INT_USE_ASM)
+ const digit_type* x_beg = x;
+ x += xlen - 3;
 
- #if defined(__GNU__)
- #if defined(__386__)
- #include <boost/mp_math/mp_int/detail/asm/x86/gnu_386_primitive_ops.hpp>
- #endif
- #endif
+ digit_type q_hat = div3by2(x, y + ylen - 2);
+ *(ws + ylen) = multiply_by_digit(ws, y, ylen, q_hat);
 
-#endif
+ const digit_type borrow = subtract_digits(ws, x, ws, ylen + 1);
+ if (borrow)
+ {
+ ++q_hat;
+ add_digits(ws, ws, y, ylen);
+ }
+
+ *q++ = q_hat;
+ --x;
+
+ ++ws;
+
+ // TODO need to multiply_subtract otherwise I'd need a second buffer to hold
+ // the result of multiply_by_digit
+ while (x != x_beg)
+ {
+ digit_type q_hat = div3by2(ws, y + ylen - 2);
+ *(ws + ylen) = multiply_by_digit(ws, y, ylen, q_hat);
+
+ const digit_type borrow = subtract_digits(ws, x, ws, ylen + 1);
+ if (borrow)
+ {
+ ++q_hat;
+ add_digits(ws, ws, y, ylen);
+ }
+
+ *q++ = q_hat;
+ --x;
+ *(ws - 1) = *x;
+ }
+}*/
+
+template<typename D, typename W, typename S>
+D basic_primitive_ops<D,W,S>::shift_bits_left(digit_type* x,
+ size_type xlen,
+ size_type n)
+{
+ assert(n > 0 && n < digit_bits);
+
+ // shift for msbs
+ const digit_type shift = digit_bits - n;
+
+ digit_type carry = 0;
+ while (xlen--)
+ {
+ const digit_type c = (*x >> shift);
+ *x = (*x << n) | carry;
+ carry = c;
+ ++x;
+ }
+
+ return carry;
+}
 
+template<typename D, typename W, typename S>
+void basic_primitive_ops<D,W,S>::shift_bits_right(digit_type* x,
+ size_type xlen,
+ size_type n)
+{
+ assert(n > 0 && n < digit_bits);
+
+ const digit_type mask = (digit_type(1) << n) - 1;
+
+ // shift for lsb
+ const digit_type shift = digit_bits - n;
+
+ x += xlen;
+
+ digit_type carry = 0;
+ while (xlen--)
+ {
+ --x;
+ const digit_type c = *x & mask;
+ *x = (*x >> n) | (carry << shift);
+ carry = c;
+ }
+}
+
+template<typename D, typename W, typename S>
+int basic_primitive_ops<D,W,S>::compare_magnitude(const digit_type* x,
+ size_type xlen,
+ const digit_type* y,
+ size_type ylen)
+{
+ if (xlen > ylen)
+ return 1;
+
+ if (xlen < ylen)
+ return -1;
+
+ // compare all digits
+ x += xlen;
+ y += ylen;
+ while (xlen--)
+ {
+ --x; --y;
+ if (*x > *y)
+ return 1;
+ if (*x < *y)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+// 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>
+{};
+
+
+#else
+
+template<typename DigitT, typename SizeT>
+struct basic_primitive_ops
+{
+ typedef DigitT digit_type;
+ typedef SizeT size_type;
+
+ static const digit_type digit_bits = std::numeric_limits<digit_type>::digits;
+
+ // ADD ------------------------------------
+
+ // z = x + y, returns carry
+ static digit_type add(digit_type& z, digit_type x, digit_type y);
+
+ // z += x, returns carry
+ static digit_type add(digit_type& z, digit_type x);
+
+ // add y to the digits in x and store result in z
+ // xlen must be > 0
+ // returns: the last carry (it will not get stored in z)
+ static digit_type add_single_digit(digit_type* z,
+ const digit_type* x, size_type xlen,
+ digit_type y);
+
+ // 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
+ // returns last carry
+ static digit_type add_smaller_magnitude(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen);
+
+ // SUB ------------------------------------
+
+ // z = x - y, returns borrow
+ static digit_type sub(digit_type& z, digit_type x, digit_type y);
+
+ // z -= x, returns borrow
+ static digit_type sub(digit_type& z, digit_type x);
+
+ // subtracts x from the digits in y and store result in z
+ static void subtract_single_digit(digit_type* z,
+ const digit_type* x, size_type xlen,
+ digit_type y);
+
+ // 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 ------------------------------------
+
+ // z = x * y, returns high part of the product
+ static digit_type mul(digit_type& z, digit_type x, digit_type y);
+
+ // z *= x, returns high part of the product
+ static digit_type mul(digit_type& z, digit_type x);
+
+ // 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* x, size_type xlen,
+ digit_type y);
+
+ // z = x * 2
+ static digit_type multiply_by_two(digit_type* z,
+ const digit_type* x, size_type len);
+
+ // z = x * y; precondition: xlen >= ylen
+ static void long_mul(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen);
+
+ // z = x * y; precondition: xlen >= ylen
+ static void comba_mul(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen);
+
+ // 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 xylen);
+
+ // z = x * y; precondition: xlen >= ylen and workspace must have at least ylen
+ // digits this function is only used by the integral ops interaction code, it
+ // allows x and z to be the same pointer.
+ static void comba_mul(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ digit_type* workspace);
+
+ // computes the lower num digits of the product of x and y
+ static void comba_mul_lo(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num);
+
+ // computes the high product of x and y without num least significant digits
+ // basically the result is: z = (x*y) >> radix^num
+ static void comba_mul_hi(digit_type* z, const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num);
+
+ // SQR ------------------------------------
+
+ // z = x * x;
+ static void comba_sqr(digit_type* z, const digit_type* x, size_type xlen);
+
+ // MADD ------------------------------------
+
+ // z = z + x * y, returns carry
+ static digit_type multiply_add(digit_type& z,
+ digit_type x, digit_type y);
+
+ // z = z + x * y, returns carry
+ static digit_type multiply_add(digit_type& z_hi, digit_type& z_lo,
+ digit_type x, digit_type y);
+
+ // z = z + x * y
+ static digit_type multiply_add_digits(digit_type* z,
+ const digit_type* x,
+ digit_type y,
+ size_type n);
+
+ // DIV -------------------------------------
+
+ // z = x / 2
+ static void divide_by_two(digit_type* z, const digit_type* x, size_type len);
+
+ // z = x / y
+ // returns remainder
+ static digit_type divide_by_digit(digit_type* z,
+ const digit_type* x, size_type xlen,
+ digit_type y);
+
+ // SHIFT -----------------------------------
+
+ // shifts x by n bits to the left, where n > 0 && n < digit_bits
+ // returns carry
+ static digit_type shift_bits_left(digit_type* x, size_type xlen, size_type n);
+
+ // shifts x by n bits to the right, where n > 0 && n < digit_bits
+ static void shift_bits_right(digit_type* x, size_type xlen, size_type n);
+
+ // CMP -------------------------------------
+
+ // returns 1 if x > y
+ // returns 0 if x == y
+ // returns -1 if x < y
+ static int compare_magnitude(const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen);
+
+private:
+
+ // divides half digits [x1, x2, x3] by [y1, y2] and returns remainder
+ // this function is used by divide_by_digit
+ static digit_type divide_half_digits(digit_type& q,
+ digit_type x12, digit_type x3,
+ digit_type y1, digit_type y2);
+};
+
+
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::add(digit_type& z, digit_type x, digit_type y)
+{
+ z = x + y;
+ return z < x;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::add(digit_type& z, digit_type x)
+{
+ z += x;
+ return z < x;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::add_single_digit(digit_type* z,
+ const digit_type* x,
+ size_type xlen,
+ digit_type y)
+{
+ digit_type carry = add(*z++, *x++, y);
+
+ while (carry && --xlen)
+ carry = add(*z++, *x++, carry);
+
+ return carry;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::add_digits(digit_type* z,
+ const digit_type* x,
+ const digit_type* y, size_type n)
+{
+ digit_type carry = 0;
+ while (n--)
+ {
+ const digit_type c0 = add(*z, *x++, *y++);
+ const digit_type c1 = add(*z++, carry);
+ carry = c0 | c1;
+ }
+
+ return carry;
+}
+
+template<typename D, typename S>
+inline
+S basic_primitive_ops<D,S>::ripple_carry(digit_type* z,
+ const digit_type* x,
+ size_type n,
+ digit_type& carry)
+{
+ size_type i = 0;
+
+ for (; carry && (i < n); ++i)
+ carry = add(*z++, *x++, carry);
+
+ return i;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::add_smaller_magnitude(digit_type* z,
+ const digit_type* x,
+ size_type xlen,
+ const digit_type* y,
+ size_type ylen)
+{
+ digit_type carry = add_digits(z, x, y, ylen);
+
+ size_type n = ripple_carry(z + ylen, x + ylen, xlen - ylen, carry);
+
+ n += ylen;
+
+ if (n < xlen && z != x)
+ std::memcpy(z + n, x + n, sizeof(digit_type) * (xlen - n));
+
+ return carry;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::sub(digit_type& z, digit_type x, digit_type y)
+{
+ z = x - y;
+ return z > x;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::sub(digit_type& z, digit_type x)
+{
+ const digit_type tmp = z;
+ z -= x;
+ return z > tmp;
+}
+
+template<typename D, typename S>
+inline
+void
+basic_primitive_ops<D,S>::subtract_single_digit(digit_type* z,
+ const digit_type* y,
+ size_type ylen,
+ digit_type x)
+{
+ digit_type borrow = sub(*z++, *y++, x);
+
+ while (borrow && --ylen)
+ borrow = sub(*z++, *y++, borrow);
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::subtract_digits(digit_type* z,
+ const digit_type* x,
+ const digit_type* y,
+ size_type n)
+{
+ digit_type borrow = 0;
+
+ while (n--)
+ {
+ const digit_type b0 = sub(*z, *x++, *y++);
+ const digit_type b1 = sub(*z++, borrow);
+ borrow = b0 | b1;
+ }
+
+ return borrow;
+}
+
+template<typename D, typename S>
+inline
+S basic_primitive_ops<D,S>::ripple_borrow(digit_type* z,
+ const digit_type* x,
+ size_type n,
+ digit_type borrow)
+{
+ size_type i = 0;
+
+ for (; borrow && (i < n); ++i)
+ borrow = sub(*z++, *x++, borrow);
+
+ return i;
+}
+
+template<typename D, typename S>
+inline
+void basic_primitive_ops<D,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);
+
+ size_type n = ripple_borrow(z + ylen, x + ylen, xlen - ylen, borrow);
+
+ if (z != x)
+ {
+ n += ylen;
+ std::memcpy(z + n, x + n, (xlen - n) * sizeof(digit_type));
+ }
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::mul(digit_type& z_lo, digit_type x, digit_type y)
+{
+ static const digit_type lo_mask = (1 << digit_bits / 2) - 1;
+
+ const digit_type x_lo = x & lo_mask;
+ const digit_type x_hi = x >> digit_bits/2;
+ const digit_type y_lo = y & lo_mask;
+ const digit_type y_hi = y >> digit_bits/2;
+
+ const digit_type z0 = x_lo * y_lo;
+ const digit_type z1 = x_lo * y_hi;
+ const digit_type z2 = x_hi * y_lo;
+ const digit_type z3 = x_hi * y_hi;
+
+ digit_type z12 = z1 + (z0 >> digit_bits/2);
+ const digit_type carry = add(z12, z2);
+
+ z_lo = (z12 << digit_bits/2) + (z0 & lo_mask);
+
+ const digit_type z_hi = z3 + (carry << digit_bits/2) + (z12 >> digit_bits/2);
+
+ return z_hi;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::mul(digit_type& z, digit_type x)
+{
+ return mul(z, z, x);
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::multiply_by_digit(digit_type* z,
+ const digit_type* y,
+ size_type ylen,
+ digit_type x)
+{
+ digit_type carry = 0;
+
+ while (ylen--)
+ {
+ const digit_type tmp = mul(*z, *y++, x);
+ carry = tmp + add(*z++, carry);
+ }
+
+ return carry;
+}
+
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::multiply_by_two(digit_type* z,
+ const digit_type* x, size_type n)
+{
+ static const digit_type one = 1U;
+
+ digit_type carry = 0;
+
+ while (n--)
+ {
+ // get carry bit for next iteration
+ const digit_type r = *x >> (digit_bits - one);
+
+ *z++ = (*x++ << one) | carry;
+
+ carry = r;
+ }
+
+ return carry;
+}
+
+template<typename D, typename S>
+void
+basic_primitive_ops<D,S>::long_mul(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen)
+{
+ assert(xlen >= ylen);
+ z[xlen] = multiply_by_digit(z++, x, xlen, *(y++));
+ --ylen;
+ while(--ylen)
+ z[xlen] = multiply_add_digits(z++, x, xlen, *(y++));
+}
+
+template<typename D, typename S>
+void
+basic_primitive_ops<D,S>::comba_mul(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen)
+{
+ assert(xlen >= ylen);
+
+ digit_type acc_hi = 0; // accumulator for each column
+ digit_type acc_lo = 0;
+ digit_type carry_hi = 0;
+ digit_type carry_lo = 0;
+
+ // phase 1
+ for (size_type i = 0; i < ylen; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = y + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ // phase 2
+ for (size_type i = 0; i < xlen - ylen; ++i)
+ {
+ const digit_type* a = x + 1 + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = 0; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ // phase 3
+ for (size_type i = 0; i < ylen - 1; ++i)
+ {
+ const digit_type* a = x + xlen - (ylen - 1) + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = i + 1; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ *z = acc_lo;
+}
+
+template<typename D, typename S>
+void
+basic_primitive_ops<D,S>::comba_mul(digit_type* z,
+ const digit_type* x,
+ const digit_type* y, size_type xylen)
+{
+ digit_type acc_hi = 0; // accumulator for each column
+ digit_type acc_lo = 0;
+ digit_type carry_hi = 0;
+ digit_type carry_lo = 0;
+
+ // phase 1
+ for (size_type i = 0; i < xylen; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = y + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ // phase 2
+ for (size_type i = 1; i < xylen; ++i)
+ {
+ const digit_type* a = y + xylen - 1;
+ const digit_type* b = x + i;
+
+ for (size_type j = 0; j < xylen - i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a--, *b++);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ *z = acc_lo;
+}
+
+template<typename D, typename S>
+void
+basic_primitive_ops<D,S>::comba_mul(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ digit_type* workspace)
+{
+ assert(xlen >= ylen);
+
+ digit_type* w = workspace;
+ digit_type acc_hi = 0; // accumulator for each column
+ digit_type acc_lo = 0;
+ digit_type carry_hi = 0;
+ digit_type carry_lo = 0;
+
+ // phase 1
+ for (size_type i = 0; i < ylen; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = y + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *w++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ w -= ylen;
+
+ // phase 2
+ for (size_type i = 0; i < xlen - ylen; ++i)
+ {
+ const digit_type* a = x + 1 + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = 0; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = *w;
+ *w++ = acc_lo;
+
+ if (static_cast<size_type>(w - workspace) == ylen)
+ w -= ylen;
+
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ // phase 3
+ for (size_type i = 0; i < ylen - 1; ++i)
+ {
+ const digit_type* a = x + xlen - (ylen - 1) + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = i + 1; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = *w;
+ *w++ = acc_lo;
+
+ if (static_cast<size_type>(w - workspace) == ylen)
+ w -= ylen;
+
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ const digit_type* ws_index = w;
+
+ while (w < (workspace + ylen))
+ *z++ = *w++;
+
+ w = workspace;
+
+ while (w < ws_index)
+ *z++ = *w++;
+
+ *z = acc_lo;
+}
+
+template<typename D, typename S>
+void
+basic_primitive_ops<D,S>::comba_mul_lo(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num)
+{
+ //assert(xlen >= ylen);
+ assert(num <= (xlen + ylen));
+
+ digit_type acc_hi = 0; // accumulator for each column
+ digit_type acc_lo = 0;
+ digit_type carry_hi = 0;
+ digit_type carry_lo = 0;
+
+ // phase 1
+ if (num)
+ {
+ const size_type m = ylen < num ? ylen : num;
+ for (size_type i = 0; i < m; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = y + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+ }
+
+ // phase 2
+ if (num >= ylen)
+ {
+ const size_type m = xlen - ylen < num ? xlen - ylen : num;
+ for (size_type i = 0; i < m; ++i)
+ {
+ const digit_type* a = x + 1 + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = 0; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+ }
+
+ // phase 3
+ if (num >= xlen + ylen)
+ {
+ const size_type m = ylen - 1 < num ? ylen - 1 : num;
+ for (size_type i = 0; i < m; ++i)
+ {
+ const digit_type* a = x + xlen - (ylen - 1);
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = i + 1; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+ }
+
+ *z = acc_lo;
+}
+
+template<typename D, typename S>
+void
+basic_primitive_ops<D,S>::comba_mul_hi(digit_type* z,
+ const digit_type* x, size_type xlen,
+ const digit_type* y, size_type ylen,
+ size_type num)
+{
+ //assert(xlen >= ylen);
+ assert(num > 0);
+ assert(num < (xlen + ylen));
+
+ digit_type acc_hi = 0; // accumulator for each column
+ digit_type acc_lo = 0;
+ digit_type carry_hi = 0;
+ digit_type carry_lo = 0;
+
+ // phase 1
+ if (num < ylen)
+ {
+ for (size_type i = num; i < ylen; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = y + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+ }
+
+ // phase 2
+ if (num < xlen)
+ {
+ for (size_type i = num - ylen; i < xlen - ylen; ++i)
+ {
+ const digit_type* a = x + 1 + i;
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = 0; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+ }
+
+ // phase 3
+ if (num < (xlen + ylen))
+ {
+ for (size_type i = num - (xlen + ylen); i < ylen - 1; ++i)
+ {
+ const digit_type* a = x + xlen - (ylen - 1);
+ const digit_type* b = y + ylen - 1;
+
+ for (size_type j = i + 1; j < ylen; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+ }
+
+ *z = acc_lo;
+}
+
+template<typename D, typename S>
+void
+basic_primitive_ops<D,S>::comba_sqr(digit_type* z,
+ const digit_type* x,
+ size_type xlen)
+{
+ digit_type acc_hi = 0; // accumulator for each column
+ digit_type acc_lo = 0;
+ digit_type carry_hi = 0;
+ digit_type carry_lo = 0;
+
+ // phase 1
+ for (size_type i = 0; i < xlen; ++i)
+ {
+ const digit_type* a = x;
+ const digit_type* b = x + i;
+
+ for (size_type j = 0; j <= i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ // phase 2
+ for (size_type i = 1; i < xlen; ++i)
+ {
+ const digit_type* a = x + i;
+ const digit_type* b = x + xlen - 1;
+
+ for (size_type j = 0; j < xlen - i; ++j)
+ {
+ const digit_type carry = multiply_add(acc_hi, acc_lo, *a++, *b--);
+ carry_hi += add(carry_lo, carry);
+ carry_hi += add(carry_lo, acc_hi);
+ acc_hi = 0;
+ }
+
+ *z++ = acc_lo;
+ acc_lo = carry_lo;
+ carry_lo = carry_hi;
+ carry_hi = 0;
+ }
+
+ *z = acc_lo;
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::multiply_add(digit_type& z_hi, digit_type& z_lo,
+ digit_type x, digit_type y)
+{
+ static const digit_type lo_mask = (1 << digit_bits / 2) - 1;
+
+ const digit_type x_lo = x & lo_mask;
+ const digit_type x_hi = x >> digit_bits/2;
+ const digit_type y_lo = y & lo_mask;
+ const digit_type y_hi = y >> digit_bits/2;
+
+ const digit_type z0 = x_lo * y_lo;
+ const digit_type z1 = x_lo * y_hi;
+ const digit_type z2 = x_hi * y_lo;
+ const digit_type z3 = x_hi * y_hi;
+
+ digit_type z12 = z1 + (z0 >> digit_bits/2);
+ const digit_type carry = add(z12, z2);
+
+ const digit_type w_lo = (z12 << digit_bits/2) + (z0 & lo_mask);
+ const digit_type w_hi = z3 + (carry << digit_bits/2) + (z12 >> digit_bits/2);
+
+ digit_type u = add(z_lo, w_lo);
+ digit_type v = add(z_hi, u);
+
+ return v + add(z_hi, w_hi);
+}
+
+template<typename D, typename S>
+inline
+D basic_primitive_ops<D,S>::multiply_add(digit_type& z,
+ digit_type x, digit_type y)
+{
+ static const digit_type lo_mask = (1 << digit_bits / 2) - 1;
+
+ const digit_type x_lo = x & lo_mask;
+ const digit_type x_hi = x >> digit_bits/2;
+ const digit_type y_lo = y & lo_mask;
+ const digit_type y_hi = y >> digit_bits/2;
+
+ const digit_type z0 = x_lo * y_lo;
+ const digit_type z1 = x_lo * y_hi;
+ const digit_type z2 = x_hi * y_lo;
+ const digit_type z3 = x_hi * y_hi;
+
+ digit_type z12 = z1 + (z0 >> digit_bits/2);
+ const digit_type carry = add(z12, z2);
+
+ const digit_type w_lo = (z12 << digit_bits/2) + (z0 & lo_mask);
+ const digit_type w_hi = z3 + (carry << digit_bits/2) + (z12 >> digit_bits/2);
+
+ const digit_type u = add(z, w_lo);
+
+ return u + w_hi;
+}
+
+template<typename D, typename S>
+D basic_primitive_ops<D,S>::multiply_add_digits(digit_type* z,
+ const digit_type* x,
+ digit_type y,
+ size_type n)
+{
+ digit_type carry = 0;
+ while (n--)
+ {
+ carry = add(*z, carry);
+ carry += multiply_add(*z, *x, y);
+ ++z; ++x;
+ }
+
+ return carry;
+}
+
+template<typename D, typename S>
+inline
+void basic_primitive_ops<D,S>::divide_by_two(digit_type* z,
+ const digit_type* x, size_type n)
+{
+ z += n - 1;
+ x += n - 1;
+
+ digit_type carry = 0;
+
+ while (n--)
+ {
+ // get carry for next iteration
+ const digit_type r = *x & 1;
+
+ *z-- = (*x-- >> 1) | (carry << (digit_bits - 1));
+
+ carry = r;
+ }
+}
+
+template<typename D, typename S>
+D basic_primitive_ops<D,S>::divide_by_digit(digit_type* z,
+ const digit_type* x, size_type n,
+ digit_type y)
+{
+ /*if (n == 1)
+ {
+ *z = *x / y;
+ return *x % y;
+ }*/
+ static const digit_type lo_mask = (1 << digit_bits / 2) - 1;
+ static const digit_type hi_mask = lo_mask << (digit_bits / 2);
+ static const digit_type hi_bit = 1 << (digit_bits - 1);
+ static const digit_type d2 = digit_bits / 2;
+
+ z += n - 1;
+ x += n - 1;
+
+ digit_type w_hi, w_lo = 0;
+
+ if (y & hi_bit) // if y is normalized
+ {
+ while (n--)
+ {
+ w_hi = w_lo;
+ w_lo = *x--;
+ // Do a 2 digit by 1 digit division -> [w_hi, w_lo] / y
+ if (w_hi || w_lo >= y) // if w >= y
+ {
+ digit_type q_hi, q_lo;
+ const digit_type rem = divide_half_digits(
+ q_hi,
+ w_hi, (w_lo & hi_mask) >> d2,
+ (y & hi_mask) >> d2, y & lo_mask);
+
+ w_lo = divide_half_digits(
+ q_lo,
+ rem, w_lo & lo_mask,
+ (y & hi_mask) >> d2, y & lo_mask);
+
+ if (w_hi >= y)
+ ++q_lo;
+
+ *z-- = (q_hi << d2) | q_lo;
+ }
+ else
+ *z-- = 0;
+
+ // q is never larger than one digit because w_hi is always set to the
+ // remainder and thus w_hi can never be greater than y which is the
+ // precondition for producing a quotient carry.
+ // TODO we could do a 2 by 1 division before the loop, that could produce
+ // a q carry. And then continue on as usual.
+ }
+
+ return w_lo;
+ }
+ else
+ {
+ // count leading zeros
+ unsigned norm = 0;
+ while (!(y & hi_bit))
+ {
+ ++norm;
+ y <<= 1;
+ }
+
+ // we're going to normalize the number in place
+ const digit_type shift = digit_bits - norm;
+
+ w_hi = *x >> shift;
+
+ while (n--)
+ {
+ w_lo = (*x << norm);
+ if (n)
+ {
+ --x;
+ w_lo |= *x >> shift;
+ }
+
+ // Do a 2 digit by 1 digit division -> [w_hi, w_lo] / y
+ if (w_hi || w_lo >= y) // if w >= y
+ {
+ digit_type q_hi, q_lo;
+ const digit_type rem = divide_half_digits(
+ q_hi,
+ w_hi, (w_lo & hi_mask) >> d2,
+ (y & hi_mask) >> d2, y & lo_mask);
+
+ w_lo = divide_half_digits(
+ q_lo,
+ rem, w_lo & lo_mask,
+ (y & hi_mask) >> d2, y & lo_mask);
+
+ *z-- = (q_hi << d2) | q_lo;
+ }
+ else
+ *z-- = 0;
+
+ w_hi = w_lo;
+ }
+
+ return w_lo >> norm;
+ }
+}
+
+template<typename D, typename S>
+D basic_primitive_ops<D,S>::divide_half_digits(digit_type& q,
+ digit_type x12, digit_type x3,
+ digit_type y1, digit_type y2)
+{
+ const digit_type y = (y1 << digit_bits / 2) | y2;
+ //if (x12 >= y)
+ // x12 -= y;
+
+ q = x12 / y1;
+
+ const digit_type c = x12 - q * y1;
+ const digit_type D_ = q * y2;
+
+ digit_type R = (c << digit_bits / 2) | x3;
+
+ if (R < D_) // R is too large by at most 2
+ {
+ static const digit_type z = ~digit_type(0);
+ --q;
+ R += y;
+ if (R < y) // overflow
+ return z - D_ + R + 1;
+ if (R < D_)
+ {
+ --q;
+ R += y;
+ if (R < y) // overflow
+ return z - D_ + R + 1;
+ }
+ }
+
+ return R - D_;
+}
+
+template<typename D, typename S>
+D basic_primitive_ops<D,S>::shift_bits_left(digit_type* x,
+ size_type xlen,
+ size_type n)
+{
+ assert(n > 0 && n < digit_bits);
+
+ // shift for msbs
+ const digit_type shift = digit_bits - n;
+
+ digit_type carry = 0;
+ while (xlen--)
+ {
+ const digit_type c = (*x >> shift);
+ *x = (*x << n) | carry;
+ carry = c;
+ ++x;
+ }
+
+ return carry;
+}
+
+template<typename D, typename S>
+void basic_primitive_ops<D,S>::shift_bits_right(digit_type* x,
+ size_type xlen,
+ size_type n)
+{
+ assert(n > 0 && n < digit_bits);
+
+ const digit_type mask = (digit_type(1) << n) - 1;
+
+ // shift for lsb
+ const digit_type shift = digit_bits - n;
+
+ x += xlen;
+
+ digit_type carry = 0;
+ while (xlen--)
+ {
+ --x;
+ const digit_type c = *x & mask;
+ *x = (*x >> n) | (carry << shift);
+ carry = c;
+ }
+}
+
+template<typename D, typename S>
+int basic_primitive_ops<D,S>::compare_magnitude(const digit_type* x,
+ size_type xlen,
+ const digit_type* y,
+ size_type ylen)
+{
+ if (xlen > ylen)
+ return 1;
+
+ if (xlen < ylen)
+ return -1;
+
+ // compare all digits
+ x += xlen;
+ y += ylen;
+ while (xlen--)
+ {
+ --x; --y;
+ if (*x > *y)
+ return 1;
+ if (*x < *y)
+ return -1;
+ }
+
+ return 0;
+}
+
+template<typename D, typename S>
+struct primitive_ops : basic_primitive_ops<D,S>
+{};
+
+#endif
+
+
+
+
+/*
+// Here we include primitive_ops specializations that use assembler
+
+#if defined(BOOST_MP_MATH_INTEGER_USE_ASM)
+
+ #if defined(__GNU__)
+ #if defined(__386__)
+ #include <boost/mp_math/mp_int/detail/base/asm/x86/gnu_386_primitive_ops.hpp>
+ #endif
+ #endif
+
+#endif
+*/
 
 
+} // namespace base
 } // namespace detail
 } // namespace mp_math
 } // namespace boost

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/shifter.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/shifter.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,154 @@
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_SHIFTER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_SHIFTER_HPP
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+template<class ApInt, bool IsSigned=ApInt::is_signed>
+struct shifter;
+
+
+template<class ApInt>
+struct shifter<ApInt, false>
+{
+ typedef ApInt int_type;
+ typedef typename int_type::traits_type traits_type;
+ typedef typename traits_type::ops_type ops_type;
+ typedef typename int_type::digit_type digit_type;
+ typedef typename int_type::size_type size_type;
+
+ static void shift_bits_left (ApInt& z, size_type n);
+ static void shift_bits_right(ApInt& z, size_type n);
+
+ static void shift_digits_left(ApInt& z, size_type n);
+ static void shift_digits_right(ApInt& z, size_type n);
+};
+
+
+template<class ApInt>
+void shifter<ApInt,false>::shift_bits_left(ApInt& z, size_type n)
+{
+ assert(z != digit_type(0));
+
+ if (n)
+ {
+ // shift by as many digits in the bit count
+ if (n >= traits_type::radix_bits)
+ shift_digits_left(z, n / traits_type::radix_bits);
+
+ // shift any bit count < radix_bits
+ const digit_type b = static_cast<digit_type>(n % traits_type::radix_bits);
+
+ if (b)
+ {
+ const digit_type carry =
+ ops_type::shift_bits_left(z.digits(), z.size(), b);
+
+ if (carry)
+ z.push(carry);
+ }
+ }
+}
+
+template<class ApInt>
+void shifter<ApInt,false>::shift_bits_right(ApInt& z, size_type n)
+{
+ if (n)
+ {
+ // shift by as many digits in the bit count
+ if (n >= traits_type::radix_bits)
+ shift_digits_right(z, n / traits_type::radix_bits);
+
+ // shift any bit count < valid_bits
+ const digit_type b = n % traits_type::radix_bits;
+ if (b)
+ ops_type::shift_bits_right(z.digits(), z.size(), b);
+
+ z.clamp_high_digit();
+ }
+}
+
+// {A,B,C,D,E} shifted left by 2 digits becomes
+// {0,0,A,B,C,D,E}
+template<class ApInt>
+void shifter<ApInt,false>::shift_digits_left(ApInt& z, size_type n)
+{
+ assert(z != digit_type(0));
+
+ if (n == 0)
+ return;
+
+ std::memmove(z.digits() + n, z.digits(), z.size() * sizeof(digit_type));
+
+ // zero the lower digits
+ std::memset(z.digits(), 0, n * sizeof(digit_type));
+
+ z.set_size(z.size() + n);
+}
+
+// {A,B,C,D,E} shifted right by 2 digits becomes
+// {C,D,E}
+template<class ApInt>
+void shifter<ApInt,false>::shift_digits_right(ApInt& z, size_type n)
+{
+ if (n == 0)
+ return;
+
+ if (z.size() <= n)
+ {
+ z = digit_type(0);
+ return;
+ }
+
+ std::memmove(z.digits(), z.digits() + n, (z.size() - n) * sizeof(digit_type));
+
+ z.set_size(z.size() - n);
+}
+
+
+template<class ApInt>
+struct shifter<ApInt, true>
+{
+ typedef ApInt int_type;
+ typedef typename int_type::size_type size_type;
+
+ static void shift_bits_left(ApInt& z, size_type n)
+ {
+ shifter<ApInt, false>::shift_bits_left(z, n);
+ }
+
+ static void shift_bits_right(ApInt& z, size_type n)
+ {
+ shifter<ApInt, false>::shift_bits_right(z, n);
+ if (!z)
+ z.set_sign_bit(0);
+ }
+
+ static void shift_digits_left(ApInt& z, size_type n)
+ {
+ shifter<ApInt, false>::shift_digits_left(z, n);
+ }
+
+ static void shift_digits_right(ApInt& z, size_type n)
+ {
+ shifter<ApInt, false>::shift_digits_right(z, n);
+ }
+};
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/to_integral.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/to_integral.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,183 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_TO_INTEGRAL_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_TO_INTEGRAL_HPP
+
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+// TODO throw std::overflow_error?
+
+template<
+ class ApInt,
+ typename IntegralT,
+ bool fits = static_cast<unsigned int>(std::numeric_limits<IntegralT>::digits)
+ <= ApInt::traits_type::radix_bits
+>
+struct converter_base;
+
+
+template<class ApInt, typename IntegralT>
+struct converter_base<ApInt, IntegralT, false>
+{
+ typedef typename ApInt::size_type size_type;
+ static IntegralT convert(const ApInt& x, size_type x_precision);
+};
+
+
+template<class ApInt, typename IntegralT>
+IntegralT
+converter_base<ApInt, IntegralT, false>::convert(
+ const ApInt& x, size_type x_precision)
+{
+ IntegralT y = 0;
+ const typename ApInt::digit_type* d = x.digits() + x.size() - 1;
+
+ for (size_type i = 0; i < x_precision; i += ApInt::traits_type::radix_bits)
+ {
+ y <<= ApInt::traits_type::radix_bits;
+ y |= *d--;
+ }
+ return y;
+}
+
+
+template<class ApInt, typename IntegralT>
+struct converter_base<ApInt, IntegralT, true>
+{
+ typedef typename ApInt::size_type size_type;
+ static IntegralT convert(const ApInt& x, size_type /*x_precision*/)
+ {
+ return static_cast<IntegralT>(x[0]);
+ }
+};
+
+
+template<
+ class ApInt,
+ typename IntegralT,
+ bool Is_ApInt_Signed = ApInt::is_signed,
+ bool Is_IntegralT_Signed = std::numeric_limits<IntegralT>::is_signed
+>
+struct to_integral_converter;
+
+
+template<class ApInt, typename IntegralT>
+struct to_integral_converter<ApInt, IntegralT, false, false>
+{
+ typedef typename ApInt::size_type size_type;
+
+ static IntegralT convert_without_check(const ApInt& x, size_type x_precision)
+ {
+ return converter_base<ApInt, IntegralT>::convert(x, x_precision);
+ }
+
+ static void check(size_type p)
+ {
+ if (p > static_cast<size_type>(std::numeric_limits<IntegralT>::digits))
+ throw std::runtime_error("to_integral_converter::check: "
+ "integral type does not have enough precision to hold result");
+ }
+
+ static IntegralT convert(const ApInt& x)
+ {
+ const size_type p = x.precision();
+ check(p);
+ return convert_without_check(x, p);
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct to_integral_converter<ApInt, IntegralT, false, true>
+{
+ typedef typename ApInt::size_type size_type;
+ typedef typename make_unsigned<IntegralT>::type unsigned_type;
+
+ static void check(size_type p)
+ {
+ to_integral_converter<ApInt, IntegralT, false, false>::check(p);
+ }
+
+ static IntegralT convert(const ApInt& x)
+ {
+ return static_cast<IntegralT>(
+ to_integral_converter<ApInt, unsigned_type, false, false>::convert(x));
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct to_integral_converter<ApInt, IntegralT, true, false>
+{
+ typedef typename ApInt::size_type size_type;
+
+ static void check(size_type p)
+ {
+ to_integral_converter<ApInt, IntegralT, false, false>::check(p);
+ }
+
+ static IntegralT convert(const ApInt& x)
+ {
+ const size_type p = x.precision();
+ check(p);
+ if (x.is_positive())
+ return to_integral_converter<ApInt, IntegralT, false, false>::
+ convert_without_check(x, p);
+ else
+ throw std::runtime_error("to_integral_converter::convert: "
+ "cannot convert negative number to unsigned integral type");
+ }
+};
+
+
+template<class ApInt, typename IntegralT>
+struct to_integral_converter<ApInt, IntegralT, true, true>
+{
+ typedef typename ApInt::size_type size_type;
+
+ static void check(size_type p)
+ {
+ // TODO static_cast<unsigned_type>(-IntegralT::min())
+ // check if x fits into the unsigned type,
+ // if yes then convert and check against the absolute min value and the max
+ // else throw exception
+ //
+ // It is not the right thing to check only the precision, change to non
+ // static member function, add reset member function, store precision as
+ // member variable and change signature to check(const ApInt& x);
+ }
+
+ static IntegralT convert(const ApInt& x)
+ {
+ const size_type p = x.precision();
+ check(p);
+
+ typedef typename make_unsigned<IntegralT>::type unsigned_type;
+ const unsigned_type y =
+ to_integral_converter<ApInt, unsigned_type, false, false>::
+ convert_without_check(x, p);
+
+ if (x.is_positive())
+ return static_cast<IntegralT>(y);
+ else
+ return -static_cast<IntegralT>(y);
+ }
+};
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,226 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_INT_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_INT_HPP
+
+#include <boost/mp_math/integer/detail/base/unbounded_int_integral.hpp>
+#include <boost/mp_math/integer/detail/base/unbounded_uint.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+// This class template inherits from unbounded_uint and adds functionality
+// which is meaningful to signed integers.
+
+// We store the sign in the high bit of capacity_ since capacity_ isn't updated
+// as often as size_. This also allows unbounded_uint to function
+// uninhibitedly since it will only update size_ but not capacity_.
+
+template<class Traits, bool Debug>
+struct unbounded_int
+:
+ unbounded_uint<Traits, Debug>
+{
+protected:
+
+ template<typename IntegralT>
+ struct integral_ops
+ :
+ unbounded_int_integral_ops<unbounded_int<Traits>, IntegralT>
+ {};
+
+public:
+
+ typedef Traits traits_type;
+ typedef unbounded_uint<Traits, Debug> magnitude_type;
+ typedef typename magnitude_type::digit_type digit_type;
+ typedef typename magnitude_type::size_type size_type;
+
+ static const bool is_signed = true;
+
+private:
+
+ static const size_type sign_bit_ =
+ size_type(1) << (std::numeric_limits<size_type>::digits - 1U);
+
+public:
+
+ unbounded_int(){}
+
+ unbounded_int(digit_type* d, size_type size, size_type capacity)
+ :
+ magnitude_type(d, size, capacity)
+ {}
+
+ bool is_positive() const
+ {
+ return !(magnitude_type::capacity_ & sign_bit_);
+ }
+
+ bool is_negative() const
+ {
+ return magnitude_type::capacity_ & sign_bit_;
+ }
+
+ size_type capacity() const
+ {
+ return magnitude_type::capacity_ & ~sign_bit_;
+ }
+
+ void set_capacity(size_type c)
+ {
+ magnitude_type::capacity_ = c | (magnitude_type::capacity_ & sign_bit_);
+ }
+
+ int sign() const
+ {
+ return (magnitude_type::capacity_ & sign_bit_) ? -1 : 1;
+ }
+
+ void set_sign(int s)
+ {
+ if (s == 1)
+ magnitude_type::capacity_ &= ~sign_bit_;
+ else
+ magnitude_type::capacity_ |= sign_bit_;
+ }
+
+ bool sign_bit() const { return magnitude_type::capacity_ & sign_bit_; }
+
+ void set_sign_bit(bool s)
+ {
+ magnitude_type::capacity_ &= ~sign_bit_;
+ magnitude_type::capacity_ |= static_cast<size_type>(s)
+ << (std::numeric_limits<size_type>::digits - 1U);
+ }
+
+ unbounded_int& operator ++()
+ {
+ integral_ops<digit_type>::add(*this, 1);
+ return *this;
+ }
+
+ unbounded_int& operator --()
+ {
+ integral_ops<digit_type>::subtract(*this, 1);
+ return *this;
+ }
+
+ unbounded_int& operator |= (const unbounded_int& rhs)
+ {
+ bitwise_ops<unbounded_int>::or_bits(*this, *this, rhs);
+ return *this;
+ }
+
+ unbounded_int& operator &= (const unbounded_int& rhs)
+ {
+ bitwise_ops<unbounded_int>::and_bits(*this, *this, rhs);
+ return *this;
+ }
+
+ unbounded_int& operator ^= (const unbounded_int& rhs)
+ {
+ bitwise_ops<unbounded_int>::xor_bits(*this, *this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator += (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::add(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator -= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::subtract(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator *= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::multiply(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator /= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::divide(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator %= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::modulo(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator |= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::bitwise_or(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator &= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::bitwise_and(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator ^= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::bitwise_xor(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ IntegralT to_integral() const
+ {
+ return to_integral_converter<
+ unbounded_int<traits_type, Debug>, IntegralT>::convert(*this);
+ }
+
+ void truncate(size_type prec)
+ {
+ magnitude_type::truncate(prec);
+ if (magnitude_type::is_uninitialized())
+ set_sign_bit(0);
+ }
+
+ void print(bool all = false) const
+ {
+ if (is_negative())
+ std::cout << "-";
+ magnitude_type::print(all);
+ }
+};
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int_fwd.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int_fwd.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,23 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_INT_FWD_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_INT_FWD_HPP
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+template<class Traits, bool Debug = Traits::enable_debug_mode>
+struct unbounded_int;
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int_integral.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_int_integral.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,905 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_INT_INTEGRAL_OPS_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_INT_INTEGRAL_OPS_HPP
+
+#include <boost/mp_math/integer/detail/base/unbounded_int_fwd.hpp>
+#include <boost/mp_math/integer/detail/base/unbounded_uint_integral.hpp>
+
+// Here we optimize interaction with built in integral types.
+// This code is hairy and subtle.
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+// We create four partial specializations out of this class template:
+// 1) IntegralT = digit_type, is_signed = false
+// 2) IntegralT = make_signed<digit_type>, is_signed = true
+// 3) is_signed = false
+// 4) is_signed = true
+// The actual dispatching to the correct specialization is done in
+// unbounded_int_integral_ops.
+// All IntegralT that fit into a digit_type are dispatched to 1).
+// All IntegralT that fit into a 'signed digit_type' are dispatched to 2).
+// All IntegralT larger than a digit_type are dispatched to 3).
+// All IntegralT larger than a 'signed digit_type' are dispatched to 4).
+template<
+ class UnboundedInt,
+ typename IntegralT,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed
+>
+struct unbounded_int_integral_ops_impl;
+
+
+// 1)
+template<class UnboundedInt>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt,
+ typename UnboundedInt::digit_type,
+ false
+>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef typename unbounded_int_type::digit_type integral_type;
+ typedef typename unbounded_int_type::traits_type traits_type;
+
+ typedef unbounded_uint_integral_ops<
+ unbounded_int_type, integral_type
+ > magnitude_type_integral_ops;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs[0] = rhs;
+ lhs.set_size(1);
+ lhs.set_sign_bit(0);
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.is_negative())
+ return false;
+ if (lhs.size() > 1)
+ return false;
+ return lhs[0] == rhs;
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.is_negative())
+ return true;
+ if (lhs.size() > 1)
+ return false;
+ return lhs[0] < rhs;
+ }
+
+ static void add (unbounded_int_type& lhs, integral_type rhs);
+ static void subtract(unbounded_int_type& lhs, integral_type rhs);
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ multiply(lhs, lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y);
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::divide(lhs, rhs);
+ if (!lhs)
+ lhs.set_sign_bit(0);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::modulo(lhs, rhs);
+ // TODO sign
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs[0] |= rhs;
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs[0] &= rhs;
+ lhs.set_sign_bit(0);
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs[0] ^= rhs;
+ }
+};
+
+
+template<class UnboundedInt>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, typename UnboundedInt::digit_type, false
+>::add(unbounded_int_type& lhs, integral_type rhs)
+{
+ if (lhs.is_positive())
+ magnitude_type_integral_ops::add(lhs, rhs);
+ else
+ {
+ if (lhs[0] > rhs) // example: -16 + 5 = -11
+ lhs[0] -= rhs;
+ else
+ {
+ if (lhs.size() == 1) // example: -1 + 5 = 4, or -5 + 5 = 0
+ {
+ lhs[0] = rhs - lhs[0];
+ lhs.set_sign_bit(0);
+ }
+ else // example -1000 + 5 = -995
+ {
+ traits_type::ops_type::subtract_single_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+ lhs.clamp_high_digit();
+ }
+ }
+ }
+}
+
+template<class UnboundedInt>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, typename UnboundedInt::digit_type, false
+>::subtract(unbounded_int_type& lhs, integral_type rhs)
+{
+ if (lhs.is_negative())
+ {
+ const integral_type carry =
+ traits_type::ops_type::add_single_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+ if (carry)
+ lhs.push(carry);
+ return;
+ }
+
+ if (lhs.size() == 1)
+ {
+ if (lhs[0] < rhs) // example: 2 - 6 = -4
+ {
+ lhs[0] = rhs - lhs[0];
+ lhs.set_sign_bit(1);
+ }
+ else // example: 8 - 7 = 1 or 5 - 5 = 0
+ lhs[0] -= rhs;
+ }
+ else
+ {
+ traits_type::ops_type::subtract_single_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+ lhs.clamp_high_digit();
+ }
+}
+
+template<class UnboundedInt>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, typename UnboundedInt::digit_type, false
+>::multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+{
+ if (y == 0)
+ {
+ assign(z, integral_type(0));
+ return;
+ }
+ else if (y == 1)
+ return;
+
+ const integral_type carry =
+ traits_type::ops_type::multiply_by_digit(
+ z.digits(), x.digits(), x.size(), y);
+
+ if (carry)
+ z.push(carry);
+}
+
+
+// 2)
+template<class UnboundedInt>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt,
+ typename make_signed<typename UnboundedInt::digit_type>::type,
+ true
+>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef typename make_signed<
+ typename unbounded_int_type::digit_type
+ >::type integral_type;
+ typedef std::numeric_limits<integral_type> integral_type_limits;
+ typedef typename unbounded_int_type::traits_type traits_type;
+
+ typedef unbounded_int_integral_ops_impl<
+ unbounded_int_type,
+ typename unbounded_int_type::digit_type
+ > impl_type;
+
+ typedef unbounded_uint_integral_ops<
+ typename unbounded_int_type::magnitude_type,
+ typename unbounded_int_type::digit_type
+ > magnitude_type_integral_ops;
+
+ static const unsigned radix_bits = traits_type::radix_bits;
+ static const unsigned q =
+ (integral_type_limits::digits + (radix_bits - 1))
+ / radix_bits;
+
+ static typename unbounded_int_type::digit_type get_absolute(integral_type x)
+ {
+ if (x >= 0)
+ return static_cast<typename unbounded_int_type::digit_type>(x);
+ else
+ return static_cast<typename unbounded_int_type::digit_type>(-x);
+ }
+
+ static bool get_sign_bit(integral_type x)
+ {
+ if (x >= 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs[0] = get_absolute(rhs);
+ lhs.set_size(1);
+ lhs.set_sign_bit(get_sign_bit(rhs));
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.sign_bit() == get_sign_bit(rhs))
+ {
+ return magnitude_type_integral_ops::equal(lhs, get_absolute(rhs));
+ }
+ else
+ return false;
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs);
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.sign_bit() == get_sign_bit(rhs))
+ magnitude_type_integral_ops::add(lhs, get_absolute(rhs));
+ else
+ impl_type::subtract(lhs, get_absolute(rhs));
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs);
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::multiply(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::divide(lhs, get_absolute(rhs));
+ if (lhs)
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ else
+ lhs.set_sign_bit(0);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::modulo(lhs, get_absolute(rhs));
+ // TODO sign
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_or(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() | get_sign_bit(rhs));
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_and(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() & get_sign_bit(rhs));
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_xor(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ }
+};
+
+
+template<class UnboundedInt>
+bool
+unbounded_int_integral_ops_impl<
+ UnboundedInt,
+ typename make_signed<typename UnboundedInt::digit_type>::type,
+ true
+>::less(const unbounded_int_type& lhs, integral_type rhs)
+{
+ if (lhs.is_positive())
+ {
+ if (rhs < 0)
+ return false;
+ else
+ return magnitude_type_integral_ops::less(lhs, get_absolute(rhs));
+ }
+ else
+ {
+ if (rhs >= 0)
+ return true;
+ else
+ {
+ if (lhs.size() <= q)
+ {
+ typedef to_integral_converter<
+ unbounded_int_type, integral_type> converter_type;
+
+ converter_type c;
+
+ const integral_type x = c.convert(lhs);
+
+ return x < rhs;
+ }
+ else
+ return true;
+ }
+ }
+
+}
+
+template<class UnboundedInt>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt,
+ typename make_signed<typename UnboundedInt::digit_type>::type,
+ true
+>::subtract(unbounded_int_type& lhs, integral_type rhs)
+{
+ if (lhs.is_positive())
+ {
+ if (rhs >= 0)
+ impl_type::subtract(lhs, get_absolute(rhs));
+ else
+ magnitude_type_integral_ops::add(lhs, get_absolute(rhs));
+ }
+ else
+ {
+ if (rhs >= 0)
+ magnitude_type_integral_ops::add(lhs, get_absolute(rhs));
+ else
+ impl_type::subtract(lhs, get_absolute(rhs));
+ }
+}
+
+
+// 3
+template<class UnboundedInt, typename IntegralT>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, false
+>
+:
+ unbounded_uint_integral_ops_impl<UnboundedInt, IntegralT, false>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef IntegralT integral_type;
+ typedef typename unbounded_int_type::traits_type traits_type;
+
+ typedef unbounded_uint_integral_ops<
+ typename unbounded_int_type::magnitude_type,
+ integral_type
+ > magnitude_type_integral_ops;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::assign(lhs, rhs);
+ lhs.set_sign_bit(0);
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.is_negative())
+ return false;
+ return magnitude_type_integral_ops::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.is_negative())
+ return true;
+ return magnitude_type_integral_ops::less(lhs, rhs);
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.is_positive())
+ magnitude_type_integral_ops::add(lhs, rhs);
+ else
+ subtract_smaller(lhs, rhs, 0);
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.is_negative())
+ magnitude_type_integral_ops::add(lhs, rhs);
+ else
+ subtract_smaller(lhs, rhs, ~lhs.sign_bit());
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::multiply(lhs, rhs);
+ if (!lhs)
+ lhs.set_sign_bit(0);
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::divide(lhs, rhs);
+ if (!lhs)
+ lhs.set_sign_bit(0);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::modulo(lhs, rhs);
+ if (!lhs)
+ lhs.set_sign_bit(0);
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_and(lhs, rhs);
+ lhs.set_sign_bit(0);
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_xor(lhs, rhs);
+ lhs.set_sign_bit(lhs.sign_bit() ^ 0);
+ }
+
+ static void subtract_smaller(unbounded_int_type& lhs,
+ integral_type rhs,
+ bool final_sign);
+};
+
+
+template<class UnboundedInt, typename IntegralT>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, false
+>::subtract_smaller(unbounded_int_type& lhs,
+ integral_type rhs,
+ bool final_sign)
+{
+ static const unsigned radix_bits = traits_type::radix_bits;
+
+ static const unsigned q =
+ (std::numeric_limits<integral_type>::digits + (radix_bits - 1))
+ / radix_bits;
+
+ typedef unbounded_uint<traits_type> unbounded_uint_type;
+
+ typename traits_type::digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ const unbounded_uint_type* x;
+ const unbounded_uint_type* y;
+
+ if (!unbounded_uint_integral_ops<
+ unbounded_int_type, integral_type>::less(lhs, rhs)) // lhs >= rhs
+ {
+ x = &lhs;
+ y = &tmp;
+ }
+ else
+ {
+ x = &tmp;
+ y = &lhs;
+ lhs.set_sign_bit(final_sign);
+ }
+
+ traits_type::ops_type::sub_smaller_magnitude(
+ lhs.digits(), x->digits(), x->size(),
+ y->digits(), y->size());
+
+ lhs.set_size(x->size());
+ lhs.clamp();
+
+ if (!lhs)
+ lhs.set_sign_bit(0);
+}
+
+
+// 4
+template<class UnboundedInt, typename IntegralT>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, true
+>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef IntegralT integral_type;
+ typedef std::numeric_limits<integral_type> integral_type_limits;
+ typedef typename unbounded_int_type::traits_type traits_type;
+ typedef typename make_unsigned<integral_type>::type unsigned_integral_type;
+
+ typedef unbounded_uint_integral_ops<
+ typename unbounded_int_type::magnitude_type,
+ unsigned_integral_type
+ > magnitude_type_integral_ops;
+
+ static const unsigned radix_bits = traits_type::radix_bits;
+ static const unsigned q =
+ (integral_type_limits::digits + (radix_bits - 1))
+ / radix_bits;
+
+ static unsigned_integral_type get_absolute(integral_type x)
+ {
+ if (x >= 0)
+ return static_cast<unsigned_integral_type>(x);
+ else
+ return static_cast<unsigned_integral_type>(-x);
+ }
+
+ static bool get_sign_bit(integral_type x)
+ {
+ if (x >= 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::assign(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(get_sign_bit(rhs));
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.sign_bit() != get_sign_bit(rhs))
+ return false;
+ return magnitude_type_integral_ops::equal(lhs, get_absolute(rhs));
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs);
+
+ static void add (unbounded_int_type& lhs, integral_type rhs);
+ static void subtract(unbounded_int_type& lhs, integral_type rhs);
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::multiply(lhs, get_absolute(rhs));
+ if (lhs)
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ else
+ lhs.set_sign_bit(0);
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ magnitude_type_integral_ops::multiply(z, x, get_absolute(y));
+ if (z)
+ z.set_sign_bit(x.sign_bit() ^ get_sign_bit(y));
+ else
+ z.set_sign_bit(0);
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::divide(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ }
+
+static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::modulo(lhs, get_absolute(rhs));
+ // TODO sign
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_or(lhs, rhs);
+ lhs.set_sign_bit(lhs.sign_bit() | get_sign_bit(rhs));
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_and(lhs, rhs);
+ lhs.set_sign_bit(lhs.sign_bit() & get_sign_bit(rhs));
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ magnitude_type_integral_ops::bitwise_xor(lhs, rhs);
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ }
+};
+
+
+template<class UnboundedInt, typename IntegralT>
+bool
+unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, true>::less(const unbounded_int_type& lhs,
+ integral_type rhs)
+{
+ if (lhs.is_positive())
+ {
+ if (rhs < 0)
+ return false;
+ else
+ return magnitude_type_integral_ops::less(lhs, get_absolute(rhs));
+ }
+ else
+ {
+ if (rhs >= 0)
+ return true;
+ else
+ {
+ if (lhs.size() <= q)
+ {
+ typedef to_integral_converter<
+ unbounded_int_type, integral_type> converter_type;
+
+ converter_type c;
+
+ const integral_type x = c.convert(lhs);
+
+ return x < rhs;
+ }
+ else
+ return true;
+ }
+ }
+}
+
+template<class UnboundedInt, typename IntegralT>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, true>::add(unbounded_int_type& lhs,
+ integral_type rhs)
+{
+ if (lhs.sign_bit() == get_sign_bit(rhs))
+ magnitude_type_integral_ops::add(lhs, get_absolute(rhs));
+ else
+ subtract_smaller(lhs, rhs, get_sign_bit(rhs));
+}
+
+template<class UnboundedInt, typename IntegralT>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, true>::subtract(unbounded_int_type& lhs,
+ integral_type rhs)
+{
+ if (lhs.sign_bit() != get_sign_bit(rhs))
+ magnitude_type_integral_ops::add(lhs, get_absolute(rhs));
+ else
+ subtract_smaller(lhs, rhs, ~lhs.sign_bit());
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////
+
+template<
+ class UnboundedInt,
+ typename IntegralT,
+ bool less_equal =
+ std::numeric_limits<IntegralT>::is_signed ?
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<
+ typename make_signed<typename UnboundedInt::digit_type>::type
+ >::digits
+ ):
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<typename UnboundedInt::digit_type>::digits
+ )
+>
+struct unbounded_int_integral_ops;
+
+
+// Dispatches integral types that fit into a digit_type by casting it to
+// digit_type or signed digit_type and using the specialization at the top.
+template<
+ class UnboundedInt,
+ typename IntegralT
+>
+struct unbounded_int_integral_ops<UnboundedInt,IntegralT,true>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedInt unbounded_int_type;
+ typedef IntegralT integral_type;
+
+ typedef unbounded_int_integral_ops_impl<
+ unbounded_int_type,
+ typename mpl::if_<
+ is_signed<integral_type>,
+ typename make_signed<
+ typename unbounded_int_type::digit_type
+ >::type,
+ typename unbounded_int_type::digit_type
+ >::type
+ > impl_type;
+
+ typedef typename impl_type::integral_type to_integral_type;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, static_cast<to_integral_type>(y));
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, static_cast<to_integral_type>(rhs));
+ }
+};
+
+
+template<
+ class UnboundedInt,
+ typename IntegralT
+>
+struct unbounded_int_integral_ops<UnboundedInt,IntegralT,false>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedInt unbounded_int_type;
+ typedef IntegralT integral_type;
+
+ typedef unbounded_int_integral_ops_impl<
+ unbounded_int_type, integral_type
+ > impl_type;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, rhs);
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, y);
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, rhs);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, rhs);
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,881 @@
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_UINT_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_UINT_HPP
+
+#include <algorithm> // swap
+#include <cassert>
+#include <iostream>
+#include <iterator> // reverse_iterator
+#include <boost/config.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/mp_math/integer/detail/base/adder.hpp>
+#include <boost/mp_math/integer/detail/base/bitwise_ops.hpp>
+#include <boost/mp_math/integer/detail/base/shifter.hpp>
+#include <boost/mp_math/integer/detail/base/to_integral.hpp>
+#include <boost/mp_math/integer/detail/base/unbounded_uint_integral.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+// The unbounded_uint_common class template provide all the functions that
+// don't need to allocate memory. This is useful for the optimization of some
+// high level algorithms where you allocate a pool of memory once and then
+// construct some unbounded_uint objects in it.
+
+// Internally the least significant digit is stored at digits_[0], while the
+// most significant is stored at digits_[size_-1].
+
+template<class Traits>
+struct unbounded_uint_common
+{
+protected:
+
+ template<typename IntegralT>
+ struct integral_ops
+ :
+ unbounded_uint_integral_ops<unbounded_uint_common<Traits>, IntegralT>
+ {};
+
+public:
+
+ typedef Traits traits_type;
+ typedef typename traits_type::digit_type digit_type;
+ typedef typename traits_type::size_type size_type;
+
+ typedef digit_type& reference;
+ typedef const digit_type& const_reference;
+ typedef digit_type* iterator;
+ typedef const digit_type* const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ static const bool is_signed = false;
+
+ unbounded_uint_common(){}
+
+ unbounded_uint_common(digit_type* d, size_type size, size_type capacity)
+ :
+ digits_(d), size_(size), capacity_(capacity)
+ {}
+
+ #ifdef BOOST_HAS_RVALUE_REFS
+ void swap(unbounded_uint_common&& rhs);
+ #else
+ void swap(unbounded_uint_common& rhs);
+ #endif
+
+ iterator begin() { return digits_; }
+ iterator end () { return digits_ + size_; }
+ const_iterator begin() const { return digits_; }
+ const_iterator end () const { return digits_ + size_; }
+ 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* digits() { return digits_; }
+ const digit_type* digits() const { return digits_; }
+
+#ifdef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
+private:
+
+ typedef size_type unbounded_uint_common::*unspecified_bool_type;
+
+public:
+
+ operator unspecified_bool_type() const
+ {
+ return !(size_ == 1 && digits_[0] == 0) ?
+ &unbounded_uint_common::size_ : 0;
+ }
+#else
+ explicit operator bool() const { return !(size_ == 1 && digits_[0] == 0); }
+#endif
+
+ bool is_even() const { return (digits_[0] & 1U) == 0U; }
+ bool is_odd () const { return (digits_[0] & 1U) == 1U; }
+ bool is_initialized () const { return size_ != 0U; }
+ bool is_uninitialized() const { return size_ == 0U; }
+
+ size_type size() const { return size_; }
+ void set_size(size_type s) { size_ = s; }
+
+ size_type capacity() const { return capacity_; }
+ void set_capacity(size_type c) { capacity_ = c; }
+
+ void push(digit_type x) { digits_[size_++] = x; }
+ void pop() { --size_; }
+
+ reference least_significant() { return digits_[0]; }
+ const_reference least_significant() const { return digits_[0]; }
+
+ reference most_significant() { return digits_[size_ - 1]; }
+ const_reference most_significant() const { return digits_[size_ - 1]; }
+
+ void clamp();
+ void clamp_high_digit();
+
+ void set_bit(size_type bit)
+ {
+ digits_[bit / traits_type::radix_bits] |=
+ digit_type(1) << (bit % traits_type::radix_bits);
+ }
+
+ void clear_bit(size_type bit)
+ {
+ digits_[bit / traits_type::radix_bits] &=
+ ~(digit_type(1) << (bit % traits_type::radix_bits));
+ }
+
+ void set_bits (size_type beg, size_type end);
+ void clear_bits(size_type beg, size_type end);
+
+ void truncate(size_type prec);
+
+ size_type precision() const;
+
+ void set_precision(size_type bits)
+ {
+ size_ = (bits + (traits_type::radix_bits - 1)) / traits_type::radix_bits;
+ }
+
+ void zero();
+
+ size_type count_trailing_zero_bits() const;
+
+ unbounded_uint_common& operator ++()
+ {
+ integral_ops<digit_type>::add(*this, 1);
+ return *this;
+ }
+
+ unbounded_uint_common& operator --()
+ {
+ integral_ops<digit_type>::subtract(*this, 1);
+ return *this;
+ }
+
+ unbounded_uint_common& operator <<= (size_type);
+ unbounded_uint_common& operator >>= (size_type);
+
+ unbounded_uint_common& operator += (const unbounded_uint_common&);
+ unbounded_uint_common& operator -= (const unbounded_uint_common&);
+
+ unbounded_uint_common& operator |= (const unbounded_uint_common& rhs)
+ {
+ bitwise_ops<unbounded_uint_common>::or_bits(*this, *this, rhs);
+ return *this;
+ }
+
+ unbounded_uint_common& operator &= (const unbounded_uint_common& rhs)
+ {
+ bitwise_ops<unbounded_uint_common>::and_bits(*this, *this, rhs);
+ return *this;
+ }
+
+ unbounded_uint_common& operator ^= (const unbounded_uint_common& rhs)
+ {
+ bitwise_ops<unbounded_uint_common>::xor_bits(*this, *this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator += (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::add(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator -= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::subtract(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator *= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::multiply(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator /= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::divide(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator %= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::modulo(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator |= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::bitwise_or(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator &= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::bitwise_and(*this, rhs);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint_common&>::type
+ operator ^= (IntegralT rhs)
+ {
+ integral_ops<IntegralT>::bitwise_xor(*this, rhs);
+ return *this;
+ }
+
+ // TODO it may not be possible to do the string stuff correctly because we
+ // can't just call *this += uint_type(s). We could implement some kind of
+ // digit_type iterator that iterates over the string and returns a digit_type.
+ // and then write the algorithm in such a way that it retrieves the next digit
+ // on demand. This may be too slow for things like *= wich jumps all over the
+ // place with its memory accesses.
+ template<typename charT> unbounded_uint_common& operator += (const charT*);
+ template<typename charT> unbounded_uint_common& operator -= (const charT*);
+ template<typename charT> unbounded_uint_common& operator |= (const charT*);
+ template<typename charT> unbounded_uint_common& operator &= (const charT*);
+ template<typename charT> unbounded_uint_common& operator ^= (const charT*);
+
+ template<typename charT, class traits, class alloc>
+ unbounded_uint_common&
+ operator += (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint_common&
+ operator -= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint_common&
+ operator |= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint_common&
+ operator &= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint_common&
+ operator ^= (const std::basic_string<charT,traits,alloc>&);
+
+ void print(bool all = false) const;
+
+ template<typename IntegralT>
+ IntegralT to_integral() const
+ {
+ return to_integral_converter<
+ unbounded_uint_common<traits_type>, IntegralT>::convert(*this);
+ }
+
+protected:
+
+ digit_type* digits_;
+ size_type size_;
+ size_type capacity_;
+};
+
+
+template<class Traits>
+#ifdef BOOST_HAS_RVALUE_REFS
+void unbounded_uint_common<Traits>::swap(unbounded_uint_common&& rhs)
+#else
+void unbounded_uint_common<Traits>::swap(unbounded_uint_common& rhs)
+#endif
+{
+ std::swap(digits_, rhs.digits_ );
+ std::swap(size_, rhs.size_ );
+ std::swap(capacity_, rhs.capacity_);
+}
+
+template<class Traits>
+inline void swap(unbounded_uint_common<Traits>& x,
+ unbounded_uint_common<Traits>& y)
+{
+ x.swap(y);
+}
+
+#ifdef BOOST_HAS_RVALUE_REFS
+template<class Traits>
+inline void swap(unbounded_uint_common<Traits>&& x,
+ unbounded_uint_common<Traits>& y)
+{
+ x.swap(y);
+}
+
+template<class Traits>
+inline void swap(unbounded_uint_common<Traits>& x,
+ unbounded_uint_common<Traits>&& y)
+{
+ x.swap(y);
+}
+#endif
+
+// This is used to ensure that leading zero digits are trimmed.
+template<class Traits>
+void unbounded_uint_common<Traits>::clamp()
+{
+ while (size_ > 1U && digits_[size_-1] == 0U)
+ --size_;
+}
+
+// For when we know that only one leading zero digit may exist.
+template<class Traits>
+inline void unbounded_uint_common<Traits>::clamp_high_digit()
+{
+ if (size_ > 1U && digits_[size_-1] == 0U)
+ --size_;
+}
+
+template<class Traits>
+void
+unbounded_uint_common<Traits>::set_bits(size_type beg, size_type end)
+{
+ const size_type beg_index = beg / traits_type::digit_bits;
+ const size_type end_index = end / traits_type::digit_bits;
+ const size_type first_bits = beg % traits_type::digit_bits;
+ const size_type last_bits = end % traits_type::digit_bits;
+
+ static const digit_type z = ~digit_type(0);
+
+ digit_type mask = z << first_bits;
+ if (beg_index == end_index && last_bits)
+ mask &= z >> (traits_type::digit_bits - last_bits);
+
+ digits_[beg_index] |= mask;
+
+ for (size_type i = beg_index + ((beg % traits_type::digit_bits) ? 1 : 0);
+ i < end_index; ++i)
+ digits_[i] = traits_type::max_digit_value;
+
+ if (beg_index != end_index && last_bits)
+ digits_[end_index] |= z >> (traits_type::digit_bits - last_bits);
+}
+
+template<class Traits>
+void
+unbounded_uint_common<Traits>::clear_bits(size_type beg, size_type end)
+{
+ const size_type beg_index = beg / traits_type::digit_bits;
+ const size_type end_index = end / traits_type::digit_bits;
+ const size_type first_bits = beg % traits_type::digit_bits;
+ const size_type last_bits = end % traits_type::digit_bits;
+
+ static const digit_type z = ~digit_type(0);
+
+ digit_type mask;
+ if (first_bits)
+ mask = z >> (traits_type::digit_bits - first_bits);
+ else
+ mask = 0;
+
+ if (beg_index == end_index)
+ mask |= z << last_bits;
+
+ digits_[beg_index] &= mask;
+
+ if (beg_index != end_index)
+ {
+ std::memset(digits_ + beg_index + 1, 0,
+ sizeof(digit_type) * (end_index - beg_index - 1));
+
+ if (last_bits)
+ digits_[end_index] &= z << last_bits;
+ }
+}
+
+// TODO no need to call clamp after truncate since we call set_precision here
+template<class Traits>
+void unbounded_uint_common<Traits>::truncate(size_type prec)
+{
+ set_precision(prec);
+ const size_type last_bits = prec % traits_type::radix_bits;
+ if (last_bits)
+ {
+ static const digit_type z = ~digit_type(0);
+ const digit_type mask = z >> (traits_type::radix_bits - last_bits);
+ digits_[size_ - 1] &= mask;
+ }
+}
+
+template<class Traits>
+typename unbounded_uint_common<Traits>::size_type
+unbounded_uint_common<Traits>::precision() const
+{
+ if (is_initialized())
+ {
+ size_type p = (size_ - 1) * traits_type::radix_bits;
+
+ // count bits in most significant digit
+ digit_type q = digits_[size_ - 1];
+ while (q > 0U)
+ {
+ ++p;
+ q >>= 1;
+ }
+
+ return p;
+ }
+ else
+ return 0;
+}
+
+// TODO remove this function?
+template<class Traits>
+inline void unbounded_uint_common<Traits>::zero()
+{
+ digits_[0] = 0;
+ size_ = 1;
+}
+
+// Counts the number of lsbs which are zero before the first one bit
+template<class Traits>
+typename unbounded_uint_common<Traits>::size_type
+unbounded_uint_common<Traits>::count_trailing_zero_bits() const
+{
+ static const size_type lnz[16] = {
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+ };
+
+ if (!*this)
+ return 0;
+
+ size_type bits = 0;
+
+ // scan lower digits until non-zero
+ const_iterator d = begin();
+ while (bits < size_ && *d == 0)
+ {
+ ++bits;
+ ++d;
+ }
+
+ bits *= traits_type::radix_bits;
+
+ digit_type q = *d;
+ // now scan this digit until a 1 is found
+ if ((q & 1) == 0)
+ {
+ digit_type qq;
+ do
+ {
+ qq = q & 15;
+ bits += lnz[qq];
+ q >>= 4;
+ } while (qq == 0);
+ }
+
+ return bits;
+}
+
+template<class Traits>
+void unbounded_uint_common<Traits>::print(bool all) const
+{
+ using std::cout;
+ cout << size_ << "{";
+ for (size_type i = 0; i < size(); ++i)
+ {
+ cout << static_cast<typename traits_type::word_type>(digits()[i]);
+ if (i < size() - 1)
+ cout << ",";
+ }
+ cout << "}";
+
+ if (all)
+ {
+ cout << capacity() - size() << "{";
+ for (size_type i = size(); i < capacity(); ++i)
+ {
+ cout << static_cast<typename traits_type::word_type>(digits()[i]);
+ if (i < capacity() - 1)
+ cout << ",";
+ }
+ cout << "}";
+ }
+ cout << "\n";
+}
+
+
+template<class Traits>
+unbounded_uint_common<Traits>&
+unbounded_uint_common<Traits>::operator <<= (const size_type n)
+{
+ if (*this != digit_type(0))
+ shifter<unbounded_uint_common<Traits> >::shift_bits_left(*this, n);
+ return *this;
+}
+
+template<class Traits>
+unbounded_uint_common<Traits>&
+unbounded_uint_common<Traits>::operator >>= (const size_type n)
+{
+ shifter<unbounded_uint_common<Traits> >::shift_bits_right(*this, n);
+ return *this;
+}
+
+template<class Traits>
+unbounded_uint_common<Traits>&
+unbounded_uint_common<Traits>::
+operator += (const unbounded_uint_common<Traits>& rhs)
+{
+ const unbounded_uint_common<Traits> *a, *b;
+ if (size() > rhs.size())
+ {
+ a = this;
+ b = &rhs;
+ }
+ else
+ {
+ a = &rhs;
+ b = this;
+ }
+
+ typedef adder<unbounded_uint_common<Traits> > adder_type;
+
+ adder_type::add_smaller_magnitude(*this, *a, *b);
+
+ return *this;
+}
+
+template<class Traits>
+unbounded_uint_common<Traits>&
+unbounded_uint_common<Traits>::
+operator -= (const unbounded_uint_common<Traits>& rhs)
+{
+ const unbounded_uint_common<Traits> *a, *b;
+ if (size() > rhs.size())
+ {
+ a = this;
+ b = &rhs;
+ }
+ else
+ {
+ a = &rhs;
+ b = this;
+ }
+
+ typedef adder<unbounded_uint_common<Traits> > adder_type;
+
+ adder_type::subtract_smaller_magnitude(*this, *a, *b);
+
+ return *this;
+}
+
+/*
+template<class Traits>
+unbounded_uint_common<Traits>&
+unbounded_uint_common<Traits>::
+operator |= (const unbounded_uint_common<Traits>& rhs)
+{
+ if (size() < rhs.size())
+ {
+ std::memcpy(digits() + size(),
+ rhs.digits() + size(),
+ (rhs.size() - size()) * sizeof(digit_type));
+ set_size(rhs.size());
+ }
+
+ for (size_type i = 0; i < std::min(size(), rhs.size()); ++i)
+ digits()[i] |= rhs[i];
+
+ return *this;
+}
+
+template<class Traits>
+unbounded_uint_common<Traits>&
+unbounded_uint_common<Traits>::
+operator &= (const unbounded_uint_common<Traits>& rhs)
+{
+ const size_type m = std::min(size(), rhs.size());
+
+ for (size_type i = 0; i < m; ++i)
+ digits()[i] &= rhs[i];
+
+ set_size(m);
+ clamp();
+
+ return *this;
+}
+
+template<class Traits>
+unbounded_uint_common<Traits>&
+unbounded_uint_common<Traits>::
+operator ^= (const unbounded_uint_common<Traits>& rhs)
+{
+ const size_type min = std::min(size(), rhs.size());
+
+ if (size() < rhs.size())
+ {
+ std::memcpy(digits() + size(),
+ rhs.digits() + size(),
+ (rhs.size() - size()) * sizeof(digit_type));
+ set_size(rhs.size());
+ }
+
+ for (size_type i = 0; i < min; ++i)
+ digits()[i] ^= rhs[i];
+
+ clamp();
+
+ return *this;
+}*/
+
+
+
+
+
+
+
+/*
+
+// x += y
+template<class Traits, bool Debug>
+void add_smaller_magnitude(unbounded_uint<Traits,Debug>& x,
+ const unbounded_uint<Traits,Debug>& y)
+{
+ assert(x.size() > y.size());
+
+ const digit_type carry =
+ traits_type::ops_type::add_digits(x.digits(),
+ x.digits(),
+ y.digits(), y.size());
+
+ size_type n =
+ traits_type::ops_type::ripple_carry(x.digits() + y.size(),
+ x.digits() + y.size(),
+ x.size() - y.size(), carry);
+ n += y.size();
+
+ if (n < x.size()) // this implies that there is no carry left
+ return;
+ else if (carry) // at this point n equals x->size_
+ x[n++] = carry;
+
+ x.set_size(n);
+}
+
+// x -= y
+template<class Traits, bool Debug>
+void sub_smaller_magnitude()
+{
+ traits_type::ops_type::sub_smaller_magnitude(digits(),
+ x->digits(), x->size(),
+ y->digits(), y->size());
+
+ set_size(x->size());
+
+ clamp();
+}*/
+
+
+template<class Traits>
+inline
+bool operator < (const unbounded_uint_common<Traits>& lhs,
+ const unbounded_uint_common<Traits>& rhs)
+{
+ const int b = Traits::ops_type::compare_magnitude(lhs.digits(), lhs.size(),
+ rhs.digits(), rhs.size());
+ return b == -1;
+}
+
+template<class Traits>
+inline
+bool operator > (const unbounded_uint_common<Traits>& lhs,
+ const unbounded_uint_common<Traits>& rhs)
+{
+ const int b = Traits::ops_type::compare_magnitude(lhs.digits(), lhs.size(),
+ rhs.digits(), rhs.size());
+ return b == 1;
+}
+
+template<class Traits>
+inline
+bool operator <= (const unbounded_uint_common<Traits>& lhs,
+ const unbounded_uint_common<Traits>& rhs)
+{
+ const int b = Traits::ops_type::compare_magnitude(lhs.digits(), lhs.size(),
+ rhs.digits(), rhs.size());
+ return b != 1;
+}
+
+template<class Traits>
+inline
+bool operator >= (const unbounded_uint_common<Traits>& lhs,
+ const unbounded_uint_common<Traits>& rhs)
+{
+ const int b = Traits::ops_type::compare_magnitude(lhs.digits(), lhs.size(),
+ rhs.digits(), rhs.size());
+ return b != -1;
+}
+
+
+
+
+
+
+
+// Now we add a layer of debug functionality. This functionality
+// is meant to be used by developers that develop new algorithms for this
+// library.
+template<class Traits>
+struct unbounded_uint<Traits, false>
+:
+ unbounded_uint_common<Traits>
+{
+ typedef unbounded_uint_common<Traits> base_type;
+
+ typedef Traits traits_type;
+ typedef typename traits_type::digit_type digit_type;
+ typedef typename traits_type::size_type size_type;
+
+ unbounded_uint(){}
+
+ unbounded_uint(digit_type* d, size_type size, size_type capacity)
+ :
+ base_type(d, size, capacity)
+ {}
+
+ void assert_invariants() const{}
+};
+
+
+template<class Traits>
+struct unbounded_uint<Traits, true>
+:
+ unbounded_uint_common<Traits>
+{
+ typedef unbounded_uint_common<Traits> base_type;
+
+ typedef Traits traits_type;
+ typedef typename traits_type::digit_type digit_type;
+ typedef typename traits_type::size_type size_type;
+
+ unbounded_uint(){}
+
+ unbounded_uint(digit_type* d, size_type size, size_type capacity)
+ :
+ base_type(d, size, capacity)
+ {}
+
+ // replace some inherited functions from the base class with debug versions
+/* digit_type& operator[](size_type i)
+ {
+ assert(i < base_type::size_);
+ return digits_[i];
+ }
+
+ const digit_type& operator[](size_type i) const
+ {
+ assert(i < size_)
+ return digits_[i];
+ }
+
+ void push(digit_type x)
+ {
+ assert(size_ < capacity());
+ digits_[size_++] = x;
+ }
+
+ void pop()
+ {
+ assert(size_ > 0);
+ --size_;
+ }
+
+ void set_bit (size_type bit);
+ void clear_bit(size_type bit);
+
+ void set_bits (size_type beg, size_type end);
+ void clear_bits(size_type beg, size_type end);
+
+ void set_precision(size_type bits);*/
+
+ void assert_invariants() const;
+};
+
+/*
+template<class Traits>
+void unbounded_uint<Traits,true>::set_bit(size_type bit)
+{
+ const size_type index = bit / traits_type::radix_bits;
+ assert(index < size_);
+ base_type::set_bit(bit);
+}
+
+template<class Traits>
+void unbounded_uint<Traits,true>::clear_bit(size_type bit)
+{
+ const size_type index = bit / traits_type::radix_bits;
+ assert(index < size_);
+ base_type::clear_bit(bit);
+}
+
+template<class Traits>
+void unbounded_uint<Traits,true>::set_bits(size_type beg, size_type end)
+{
+ assert(beg < end);
+ const size_type index = bit / traits_type::radix_bits;
+ assert(index < size_);
+ base_type::set_bits(beg, end);
+}
+
+template<class Traits>
+void unbounded_uint<Traits,true>::clear_bits(size_type beg, size_type end)
+{
+ assert(beg < end);
+ const size_type index = bit / traits_type::radix_bits;
+ assert(index < size_);
+ base_type::clear_bits(beg, end);
+}
+
+template<class Traits>
+void unbounded_uint<Traits,true>::set_precision(size_type bits)
+{
+ const size_type new_size = bits / traits_type::radix_bits;
+ assert(new_size < this->capacity());
+ base_type::set_precision();
+}*/
+
+template<class Traits>
+void unbounded_uint<Traits,true>::assert_invariants() const
+{
+ if (base_type::is_initialized())
+ {
+ assert(base_type::size() <= base_type::capacity());
+ if (base_type::size() > 1U)
+ assert(base_type::digits()[base_type::size()-1] != 0U);
+ }
+}
+
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint_fwd.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint_fwd.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,26 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_UINT_FWD_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_UINT_FWD_HPP
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+template<class Traits>
+struct unbounded_uint_common;
+
+template<class Traits, bool Debug = Traits::enable_debug_mode>
+struct unbounded_uint;
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint_integral.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/unbounded_uint_integral.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,1044 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_UINT_INTEGRAL_OPS_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_UNBOUNDED_UINT_INTEGRAL_OPS_HPP
+
+#include <boost/static_assert.hpp>
+#include <boost/mpl/less_equal.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/make_signed.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/mp_math/integer/detail/base/from_integral.hpp>
+#include <boost/mp_math/integer/detail/base/to_integral.hpp>
+#include <boost/mp_math/integer/detail/base/unbounded_uint_fwd.hpp>
+
+// Here we optimize interaction with built in integral types.
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+template<
+ typename IntegralT,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed
+>
+struct integral_info;
+
+
+template<typename IntegralT>
+struct integral_info<IntegralT, false>
+{
+ typedef IntegralT integral_type;
+ typedef typename make_signed<integral_type>::type signed_integral_type;
+
+ static const bool is_signed = false;
+};
+
+
+template<typename IntegralT>
+struct integral_info<IntegralT, true>
+{
+ typedef IntegralT integral_type;
+ typedef typename make_unsigned<integral_type>::type unsigned_integral_type;
+
+ static unsigned_integral_type get_absolute(integral_type x)
+ {
+ if (x >= 0)
+ return static_cast<unsigned_integral_type>(x);
+ else
+ return static_cast<unsigned_integral_type>(-x);
+ }
+
+ static bool get_sign_bit(integral_type x)
+ {
+ if (x >= 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ static const bool is_signed = true;
+};
+
+
+// We create four partial specializations out of this class template:
+// 1) IntegralT = digit_type, is_signed = false
+// 2) IntegralT = make_signed<digit_type>, is_signed = true
+// 3) is_signed = false
+// 4) is_signed = true
+// The actual dispatching to the correct specialization is done in
+// unbounded_uint_integral_ops.
+// All IntegralT that fit into a digit_type are dispatched to 1).
+// All IntegralT that fit into a 'signed digit_type' are dispatched to 2).
+// All IntegralT larger than a digit_type are dispatched to 3).
+// All IntegralT larger than a 'signed digit_type' are dispatched to 4).
+template<
+ class UnboundedUInt,
+ typename IntegralT,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed
+>
+struct unbounded_uint_integral_ops_impl;
+
+
+// 1)
+template<class UnboundedUInt>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUInt,
+ typename UnboundedUInt::digit_type,
+ false
+>
+{
+ typedef UnboundedUInt unbounded_uint_type;
+ typedef typename unbounded_uint_type::digit_type integral_type;
+ typedef typename unbounded_uint_type::traits_type traits_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs[0] = rhs;
+ lhs.set_size(1);
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ if (lhs.size() > 1)
+ return false;
+ return lhs[0] == rhs;
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ if (lhs.size() > 1)
+ return false;
+ return lhs[0] < rhs;
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ const integral_type carry =
+ traits_type::ops_type::add_single_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+ if (carry)
+ lhs.push(carry);
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs);
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ multiply(lhs, lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y);
+
+ static void divide (unbounded_uint_type& lhs, integral_type rhs);
+ static void modulo (unbounded_uint_type& lhs, integral_type rhs);
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs[0] |= rhs;
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs[0] &= rhs;
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs[0] ^= rhs;
+ }
+};
+
+
+template<class UnboundedUInt>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, typename UnboundedUInt::digit_type, false
+>::subtract(unbounded_uint_type& lhs, integral_type rhs)
+{
+ if (!less(lhs, rhs))
+ {
+ if (lhs.size() == 1)
+ lhs[0] -= rhs;
+ else
+ {
+ traits_type::ops_type::subtract_single_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+ lhs.clamp_high_digit();
+ }
+ }
+ else
+ throw std::runtime_error("unbounded_uint_integral_ops_impl::subtract: "
+ "result is negative");
+}
+
+template<class UnboundedUInt>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, typename UnboundedUInt::digit_type, false
+>::multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+{
+ if (y == 0)
+ {
+ assign(z, integral_type(0));
+ return;
+ }
+ else if (y == 1)
+ return;
+
+ const integral_type carry =
+ traits_type::ops_type::multiply_by_digit(
+ z.digits(), x.digits(), x.size(), y);
+
+ if (carry)
+ z.push(carry);
+}
+
+template<class UnboundedUInt>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, typename UnboundedUInt::digit_type, false
+>::divide(unbounded_uint_type& lhs, integral_type rhs)
+{
+ if (rhs == 0)
+ throw std::domain_error(
+ "unbounded_uint_integral_ops_impl::divide: division by zero");
+
+ if (rhs == 1 || !lhs)
+ return;
+
+ const bool is_power_of_two = (rhs & (rhs-1)) == 0;
+
+ if (!is_power_of_two)
+ traits_type::ops_type::divide_by_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+ else
+ {
+ integral_type i = 2;
+ while ((i < traits_type::radix_bits) && (rhs != integral_type(1) << i))
+ ++i;
+
+ traits_type::ops_type::shift_bits_right(lhs.digits(), lhs.size(), i);
+ }
+
+ lhs.clamp_high_digit();
+}
+
+template<class UnboundedUInt>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, typename UnboundedUInt::digit_type, false
+>::modulo(unbounded_uint_type& lhs, integral_type rhs)
+{
+ if (rhs == 0)
+ throw std::domain_error(
+ "unbounded_uint_integral_ops_impl::modulo: division by zero");
+
+ if (rhs == 1 || !lhs)
+ {
+ assign(lhs, 0);
+ return;
+ }
+
+ const bool is_power_of_two = (rhs & (rhs-1)) == 0;
+
+ if (!is_power_of_two)
+ lhs[0] =
+ traits_type::ops_type::divide_by_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+ else
+ {
+ integral_type i = 2;
+ while ((i < traits_type::radix_bits) && (rhs != integral_type(1) << i))
+ ++i;
+
+ lhs[0] &= ((integral_type(1) << i) - 1);
+ }
+
+ lhs.set_size(1);
+}
+
+
+
+// 2)
+// just casts to digit_type and dispatches to above specialization
+template<class UnboundedUInt>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUInt,
+ typename make_signed<typename UnboundedUInt::digit_type>::type,
+ true
+>
+{
+ typedef UnboundedUInt unbounded_uint_type;
+ typedef typename make_signed<
+ typename unbounded_uint_type::digit_type
+ >::type integral_type;
+
+ typedef typename unbounded_uint_type::digit_type unsigned_integral_type;
+
+ typedef unbounded_uint_integral_ops_impl<
+ unbounded_uint_type,
+ unsigned_integral_type
+ > impl_type;
+
+ static unsigned_integral_type promote(integral_type rhs)
+ {
+ // TODO if (rhs < 0)
+ // throw integral_promotion_error();
+ return static_cast<unsigned_integral_type>(rhs);
+ }
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, static_cast<unsigned_integral_type>(y));
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+};
+
+
+// 3
+template<class UnboundedUInt, typename IntegralT>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false
+>
+{
+ typedef UnboundedUInt unbounded_uint_type;
+ typedef IntegralT integral_type;
+ typedef std::numeric_limits<integral_type> integral_type_limits;
+ typedef typename unbounded_uint_type::traits_type traits_type;
+
+ static const unsigned radix_bits = traits_type::radix_bits;
+ static const unsigned max_digit_value = traits_type::max_digit_value;
+
+ static const unsigned q =
+ (integral_type_limits::digits + (radix_bits - 1))
+ / radix_bits;
+
+ static void assign (unbounded_uint_type& lhs, integral_type rhs);
+ static bool equal (const unbounded_uint_type& lhs, integral_type rhs);
+ static bool less (const unbounded_uint_type& lhs, integral_type rhs);
+ static void add (unbounded_uint_type& lhs, integral_type rhs);
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs);
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs);
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y);
+ static void divide (unbounded_uint_type& lhs, integral_type rhs);
+ static void modulo (unbounded_uint_type& lhs, integral_type rhs);
+
+ static void bitwise_or (unbounded_uint_type& lhs, integral_type rhs);
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs);
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs);
+
+ typedef typename traits_type::digit_type digit_type;
+};
+
+
+template<class UnboundedUInt, typename IntegralT>
+const unsigned unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::q;
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::assign(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ lhs[0] = static_cast<digit_type>(rhs);
+ lhs.set_size(1);
+ }
+ else
+ {
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(lhs, rhs);
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+bool
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::equal(const unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (lhs.size() <= q)
+ {
+ typedef to_integral_converter<
+ unbounded_uint_type, integral_type> converter_type;
+
+ converter_type c;
+
+ // TODO it's faster to convert from integral type but comparison is faster
+ // between integral types, measure which one is better!
+ const integral_type x = c.convert(lhs);
+
+ return x == rhs;
+ }
+
+ return false;
+}
+
+template<class UnboundedUInt, typename IntegralT>
+bool
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::less(const unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ // TODO reroute to 1) if rhs <= digit_max
+ if (lhs.size() <= q)
+ {
+ typedef to_integral_converter<
+ unbounded_uint_type, integral_type> converter_type;
+
+ converter_type c;
+
+ const integral_type x = c.convert(lhs);
+
+ return x < rhs;
+ }
+
+ return false;
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::add(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::add(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ lhs += tmp;
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::subtract(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::subtract(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ lhs -= tmp;
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::multiply(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::multiply(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ unbounded_uint_type *a, *b;
+ if (lhs.size() > tmp.size())
+ {
+ a = &lhs;
+ b = &tmp;
+ }
+ else
+ {
+ a = &tmp;
+ b = &lhs;
+ }
+
+ digit_type workspace[q];
+ traits_type::ops_type::comba_mul(lhs.digits(),
+ a->digits(), a->size(),
+ b->digits(), b->size(), workspace);
+ lhs.set_size(lhs.size() + tmp.size());
+ lhs.clamp_high_digit();
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x,
+ integral_type y)
+{
+ if (y <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::multiply(z, x, static_cast<digit_type>(y));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, y);
+
+ unbounded_uint_type *a, *b;
+ if (x.size() > tmp.size())
+ {
+ a = &x;
+ b = &tmp;
+ }
+ else
+ {
+ a = &tmp;
+ b = &x;
+ }
+
+ digit_type workspace[q];
+ traits_type::ops_type::comba_mul(z.digits(), a->digits(), a->size(),
+ b->digits(), b->size());
+ z.set_size(x.size() + tmp.size());
+ z.clamp_high_digit();
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::divide(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::divide(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ digit_type remainder_digits[q] = {0};
+
+ unbounded_uint_type remainder(remainder_digits, q, q);
+
+ //divide(lhs, &remainder, lhs, tmp);
+
+ remainder.clamp();
+
+ typedef to_integral_converter<
+ unbounded_uint_type, integral_type> converter_type;
+
+ converter_type c;
+
+ assign(lhs, c.convert_without_check(remainder, remainder.precision()));
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::modulo(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::divide(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ digit_type remainder_digits[q] = {0};
+
+ unbounded_uint_type remainder(remainder_digits, q, q);
+
+ //divide(&lhs, &remainder, lhs, tmp);
+
+ remainder.clamp();
+
+ typedef to_integral_converter<
+ unbounded_uint_type, integral_type> converter_type;
+
+ converter_type c;
+
+ assign(lhs, c.convert_without_check(remainder, remainder.precision()));
+ }
+}
+
+// TODO first need to write
+// divide(unbounded_uint_type* q, unbounded_uint_type* r,
+// const unbounded_uint_type& x, const unbounded_uint_type& y);
+// or don't implement this function if it is not possible to do so without the
+// use of temporary memory.
+
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::bitwise_or(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::bitwise_or(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ lhs |= tmp;
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::bitwise_and(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::bitwise_and(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ lhs &= tmp;
+ }
+}
+
+template<class UnboundedUInt, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, false>::bitwise_xor(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ unbounded_uint_integral_ops_impl<
+ UnboundedUInt, digit_type
+ >::bitwise_xor(lhs, static_cast<digit_type>(rhs));
+ }
+ else
+ {
+ digit_type tmp_digits[q];
+
+ unbounded_uint_type tmp(tmp_digits, q, q);
+
+ from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(tmp, rhs);
+
+ lhs ^= tmp;
+ }
+}
+
+
+// 4
+template<class UnboundedUInt, typename IntegralT>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUInt, IntegralT, true
+>
+{
+ typedef UnboundedUInt unbounded_uint_type;
+ typedef IntegralT integral_type;
+
+ typedef typename make_unsigned<integral_type>::type unsigned_integral_type;
+
+ // this is spec 3
+ typedef unbounded_uint_integral_ops_impl<
+ unbounded_uint_type,
+ unsigned_integral_type
+ > impl_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, static_cast<unsigned_integral_type>(y));
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+};
+
+
+
+
+////////////////////////////////////////////////////////////////////
+
+template<
+ class UnboundedUInt,
+ typename IntegralT,
+ bool less_equal =
+ std::numeric_limits<IntegralT>::is_signed ?
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<
+ typename make_signed<typename UnboundedUInt::digit_type>::type
+ >::digits
+ ):
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<typename UnboundedUInt::digit_type>::digits
+ )
+>
+struct unbounded_uint_integral_ops;
+
+
+// Dispatches integral types that fit into a digit_type by casting it to
+// digit_type or signed digit_type and using the specialization at the top.
+template<
+ class UnboundedUInt,
+ typename IntegralT
+>
+struct unbounded_uint_integral_ops<UnboundedUInt,IntegralT,true>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedUInt unbounded_uint_type;
+ typedef IntegralT integral_type;
+
+ typedef unbounded_uint_integral_ops_impl<
+ unbounded_uint_type,
+ typename mpl::if_<
+ is_signed<integral_type>,
+ typename make_signed<
+ typename unbounded_uint_type::digit_type
+ >::type,
+ typename unbounded_uint_type::digit_type
+ >::type
+ > impl_type;
+
+ typedef typename impl_type::integral_type to_integral_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, static_cast<to_integral_type>(y));
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, static_cast<to_integral_type>(rhs));
+ }
+};
+
+
+template<
+ class UnboundedUInt,
+ typename IntegralT
+>
+struct unbounded_uint_integral_ops<UnboundedUInt,IntegralT,false>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedUInt unbounded_uint_type;
+ typedef IntegralT integral_type;
+
+ typedef unbounded_uint_integral_ops_impl<
+ unbounded_uint_type, integral_type
+ > impl_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, rhs);
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, y);
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, rhs);
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, rhs);
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

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

Copied: sandbox/mp_math/boost/mp_math/integer/detail/divider.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/detail/div.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/div.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/divider.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,165 +1,229 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_DETAIL_DIV_HPP
-#define BOOST_MP_MATH_MP_INT_DETAIL_DIV_HPP
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_DIVIDER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_DIVIDER_HPP
 
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#include <iostream>
+#include <boost/mp_math/integer/detail/shifter.hpp>
 
 namespace boost {
 namespace mp_math {
 namespace detail {
 
-// integer signed division.
+template<class ApInt>
+struct divider
+{
+ typedef ApInt int_type;
+ typedef typename int_type::traits_type traits_type;
+ typedef typename traits_type::ops_type ops_type;
+ typedef typename int_type::digit_type digit_type;
+ typedef typename int_type::size_type size_type;
+ typedef shifter<int_type> shifter_type;
+
+ // divide a by b, optionally store remainder
+ static void classic_divide(const ApInt& a, const ApInt& b,
+ ApInt& q, ApInt* remainder = 0);
+};
+
+
+// integer signed division.
 // q*b + r == a
 // HAC pp.598 Algorithm 14.20
 //
-// Note that the description in HAC is horribly incomplete. For example, it
+// 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,
+// loop. It also doesn't consider the case that y has fewer than three digits,
 // etc..
 // The overall algorithm is as described as 14.20 from HAC but fixed to treat
 // these cases.
-
-// divide a by b, optionally store remainder
-template<class A, class T>
-void classic_divide(const mp_int<A,T>& a, const mp_int<A,T>& b,
- mp_int<A,T>& q, mp_int<A,T>* remainder = 0)
+template<class ApInt>
+void divider<ApInt>::classic_divide(const ApInt& a, const ApInt& b,
+ ApInt& q, ApInt* remainder)
 {
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::word_type word_type;
- typedef typename mp_int<A,T>::size_type size_type;
+ typedef typename traits_type::word_type word_type;
 
   if (!b)
- throw std::domain_error("mp_int::divide: division by zero");
+ throw std::domain_error("unbounded::divide: division by zero");
+
+ if (b.size() == 1)
+ {
+ q.reserve(a.size());
+ q.set_size(a.size());
+ const digit_type r =
+ ops_type::divide_by_digit(q.digits(), a.digits(), a.size(), b[0]);
+ q.clamp();
+ if (remainder)
+ *remainder = r;
+ return;
+ }
 
- // if *this < b then q=0, r = *this
- if (a.compare_magnitude(b) == -1)
+ if (ops_type::compare_magnitude(a.digits(), a.size(),
+ b.digits(), b.size()) == -1)
   {
     if (remainder)
       *remainder = a;
- q.zero();
+ q = digit_type(0);
     return;
   }
 
- q.grow_capacity(a.size() + 2);
+ q.reserve(a.size() + 2);
   q.set_size(a.size() + 2);
   std::memset(q.digits(), 0, q.size() * sizeof(digit_type));
 
- mp_int<A,T> x(a);
- mp_int<A,T> y(b);
+ ApInt x;
+ ApInt y;
+
+ x.reserve(a.size() + 1);
+ y.reserve(b.size() + 1);
 
- // fix the sign
- const int neg = (a.sign() == b.sign()) ? 1 : -1;
- x.set_sign(1);
- y.set_sign(1);
-
- // normalize both x and y, ensure that y >= beta/2, [beta == 2**valid_bits]
- size_type norm = y.precision() % mp_int<A,T>::valid_bits;
- if (norm < mp_int<A,T>::valid_bits - 1)
- {
- norm = mp_int<A,T>::valid_bits - 1 - norm;
- x <<= norm;
- y <<= norm;
+ // TODO optimize by creating shift_bits_left(digit_type* z,
+ // const digit_type* x, size_type xlen, size_type n) function and using it in
+ // the if below
+ std::memcpy(x.digits(), a.digits(), a.size() * sizeof(digit_type));
+ std::memcpy(y.digits(), b.digits(), b.size() * sizeof(digit_type));
+
+ x.set_size(a.size());
+ y.set_size(b.size());
+
+ // normalize both x and y, ensure that y >= radix/2
+ size_type norm = y.precision() % traits_type::radix_bits;
+ if (norm < traits_type::radix_bits - 1)
+ {
+ norm = traits_type::radix_bits - 1 - norm;
+ {
+ const digit_type carry =
+ ops_type::shift_bits_left(x.digits(), x.size(), norm);
+ if (carry)
+ x.push(carry);
+ }
+ {
+ const digit_type carry =
+ ops_type::shift_bits_left(y.digits(), y.size(), norm);
+ if (carry)
+ y.push(carry);
+ }
   }
   else
     norm = 0;
 
- // note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4
+ // note hac does 0 based, so if size==5 then its 0,1,2,3,4, e.g. use 4
   const size_type n = x.size() - 1;
   const size_type t = y.size() - 1;
 
   // find leading digit of the quotient
- // while (x >= y*beta**(n-t)) do { q[n-t] += 1; x -= y*beta**(n-t) }
- y.shift_digits_left(n - t); // y = y*beta**(n-t)
+ // while (x >= y*radix^(n-t)) do { q[n-t] += 1; x -= y*radix^(n-t) }
 
- while (x.compare(y) != -1)
+ // here we pretend that we shifted y by (n-t) digits to the left
+ while (ops_type::compare_magnitude(
+ x.digits() + (n-t), y.size(), y.digits(), y.size()) != -1)
   {
     ++q[n - t];
- x -= y;
+ ops_type::sub_smaller_magnitude(
+ x.digits() + (n-t), x.digits() + (n-t), y.size(), y.digits(), y.size());
+ x.clamp();
   }
 
- // reset y by shifting it back down
- y.shift_digits_right(n - t);
+ // moved temporary construction out of the loop below
+ ApInt u;
+ u.reserve(y.size() + (n - t));
 
   // find the remainder of the digits
- // step 3. for i from n down to (t + 1)
   for (size_type i = n; i >= (t + 1); --i)
   {
     if (i > x.size())
       continue;
 
- // step 3.1 if xi == yt then set q{i-t-1} to beta-1,
- // otherwise set q{i-t-1} to (xi*beta + x{i-1})/yt
+ const size_type offset = i - t - 1;
+
+ // step 3.1 if xi == yt then set q{i-t-1} to radix-1,
+ // otherwise set q{i-t-1} to (xi*radix + x{i-1})/yt
     if (x[i] == y[t])
- q[i - t - 1] = mp_int<A,T>::digit_max;
+ q[offset] = traits_type::max_digit_value;
     else
     {
       word_type tmp = static_cast<word_type>(x[i])
- << static_cast<word_type>(mp_int<A,T>::valid_bits);
+ << static_cast<word_type>(traits_type::radix_bits);
       tmp |= x[i - 1];
       tmp /= y[t];
- q[i - t - 1] = static_cast<digit_type>(tmp);
+ q[offset] = 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
+ // while (q{i-t-1} * (yt * radix + y{t-1})) >
+ // xi * radix^2 + xi-1 * radix + xi-2
     //
     // do q{i-t-1} -= 1;
 
- mp_int<A,T> t1, t2;
- t1.grow_capacity(3);
- t2.grow_capacity(3);
+ digit_type t1[3];
+ digit_type t2[3];
 
- ++q[i - t - 1];
+ ++q[offset];
     do
     {
- --q[i - t - 1];
+ --q[offset];
 
       // find left hand
- t1.zero();
       t1[0] = (t == 0) ? 0 : y[t - 1];
       t1[1] = y[t];
- t1.set_size(2);
- t1.multiply_by_digit(q[i - t - 1]);
+ t1[2] = ops_type::multiply_by_digit(t1, t1, 2, q[offset]);
 
       // find right hand
       t2[0] = (i < 2) ? 0 : x[i - 2];
       t2[1] = (i == 0) ? 0 : x[i - 1];
       t2[2] = x[i];
- t2.set_size(3);
- } while (t1.compare_magnitude(t2) == 1);
-
- // step 3.3 x = x - q{i-t-1} * y * beta**{i-t-1}
- t1 = y;
- t1.multiply_by_digit(q[i - t -1]);
- t1.shift_digits_left(i - t - 1);
- x -= t1;
+ } while (ops_type::compare_magnitude(t1, 3, t2, 3) == 1);
 
- // if x < 0 then { x = x + y*beta**{i-t-1}; q{i-t-1} -= 1; }
- if (x.is_negative())
+ // step 3.3 x = x - q{i-t-1} * y * radix^{i-t-1}
+ std::memset(u.digits(), 0, offset * sizeof(digit_type));
+ const digit_type carry =
+ ops_type::multiply_by_digit(u.digits() + offset,
+ y.digits(), y.size(), q[offset]);
+ u.set_size(y.size() + offset);
+ if (carry)
+ u.push(carry);
+ u.clamp();
+
+ // if x < 0 then { x = x + y*radix^{i-t-1}; q{i-t-1} -= 1; }
+ // We check if x will become less than zero before we subtract, in that case
+ // we adjust x before the subtraction.
+ if (ops_type::compare_magnitude(x.digits(), x.size(),
+ u.digits(), u.size()) == -1)
     {
- t1 = y;
- t1.shift_digits_left(i - t -1);
- x += t1;
+ digit_type* x_off = x.digits() + offset;
+
+ digit_type carry =
+ ops_type::add_digits(x_off, x_off, y.digits(), y.size());
 
- --q[i - t - 1] = q[i - t - 1];
+ ops_type::ripple_carry(x_off + y.size(),
+ x_off + y.size(),
+ x.size() - y.size() - offset,
+ carry);
+
+ if (carry)
+ {
+ // TODO can this happen, do I need to reserve one more digit?
+ x.push(carry);
+ }
+
+ --q[offset];
     }
+
+ ops_type::sub_smaller_magnitude(x.digits(), x.digits(), x.size(),
+ u.digits(), u.size());
+ x.clamp();
   }
 
   // now q is the quotient and x is the remainder [which we have to normalize]
-
- // get sign before writing to q
- x.set_sign(!x ? 1 : a.sign());
 
   q.clamp();
- q.set_sign(neg);
 
   if (remainder)
   {
+ // TODO optimize by having shift_right(z, x, xlen, n) function
     x >>= norm;
     remainder->swap(x);
   }

Copied: sandbox/mp_math/boost/mp_math/integer/detail/gcd.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/gcd.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,68 +1,116 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_GCD_HPP
-#define BOOST_MP_MATH_MP_INT_GCD_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_GCD_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_GCD_HPP
 
 namespace boost {
 namespace mp_math {
+namespace detail {
 
-// 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)
+
+template<class ApInt, bool IsSigned = ApInt::is_signed>
+struct gcd_finder;
+
+
+template<class ApInt>
+struct gcd_finder<ApInt, false>
+{
+ static void gcd(ApInt& z, const ApInt& a, const ApInt& b);
+ static void binary_method(ApInt& z, ApInt& u, ApInt& v);
+};
+
+
+template<class ApInt>
+void gcd_finder<ApInt, false>::gcd(ApInt& z, const ApInt& a, const ApInt& b)
 {
   // either zero then gcd is the largest
   if (!a)
- return abs(b);
+ {
+ z = b;
+ return;
+ }
+
   if (!b)
- return abs(a);
+ {
+ z = a;
+ return;
+ }
 
   // get copies of a and b we can modify
- mp_int<A,T> u = abs(a);
- mp_int<A,T> v = abs(b);
+ ApInt u(a);
+ ApInt v(b);
 
- typedef typename mp_int<A,T>::size_type size_type;
+ binary_method(z, u, v);
+}
+
+// Greatest Common Divisor using the binary method
+template<class ApInt>
+void gcd_finder<ApInt, false>::binary_method(ApInt& z, ApInt& u, ApInt& v)
+{
+ typedef typename ApInt::size_type size_type;
 
   // 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);
+ const size_type u_tzb = u.count_trailing_zero_bits();
+ const size_type v_tzb = v.count_trailing_zero_bits();
+ const size_type k = std::min(u_tzb, v_tzb);
 
   // divide out powers of two
- u >>= u_lsb;
- v >>= v_lsb;
+ u >>= u_tzb;
+ v >>= v_tzb;
 
   while (v)
   {
     if (u > v)
       u.swap(v);
-
- v.sub_smaller_magnitude(u);
+
+ v -= u;
 
     // Divide out all factors of two
- v >>= v.count_lsb();
- }
+ v >>= v.count_trailing_zero_bits();
+ }
 
- // multiply by 2**k which we divided out at the beginning
+ // multiply by 2^k which we divided out at the beginning
   u <<= k;
 
- return u;
+ swap(z, u);
 }
 
-#ifdef BOOST_HAS_VARIADIC_TMPL
-template<class A, class T, class... MpInts>
-mp_int<A,T> gcd(const mp_int<A,T>& a, const mp_int<A,T>& b, const MpInts&... args)
+
+template<class ApInt>
+struct gcd_finder<ApInt, true>
+{
+ static void gcd(ApInt& z, const ApInt& a, const ApInt& b);
+};
+
+
+template<class ApInt>
+void gcd_finder<ApInt, true>::gcd(ApInt& z, const ApInt& a, const ApInt& b)
 {
- return gcd(gcd(a, b), args...);
+ // either zero then gcd is the largest
+ if (!a)
+ {
+ z = abs(b);
+ return;
+ }
+ if (!b)
+ {
+ z = abs(a);
+ return;
+ }
+
+ // get copies of a and b we can modify
+ ApInt u = abs(a);
+ ApInt v = abs(b);
+
+ gcd_finder<ApInt, false>::binary_method(z, u, v);
 }
-#endif
 
 
+} // namespace detail
 } // namespace mp_math
 } // namespace boost
 

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/integral_ops.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,713 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#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();
-
- typedef typename MpInt::digit_type digit_type;
-
- if (rhs <= MpInt::digit_max)
- lhs[0] = static_cast<digit_type>(rhs);
- else
- {
- 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 rhs_sign = rhs < 0 ? -1 : 1;
-
- if (lhs.sign() != rhs_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;
-
- static const typename MpInt::size_type rhs_precision =
- static_cast<typename MpInt::size_type>(
- std::numeric_limits<IntegralT>::digits);
-
- if (lhs.precision() > rhs_precision)
- return lhs.sign() == -1;
-
- 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] |= static_cast<typename MpInt::digit_type>(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] &= static_cast<typename MpInt::digit_type>(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] ^= static_cast<typename MpInt::digit_type>(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
-

Copied: sandbox/mp_math/boost/mp_math/integer/detail/jacobi.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/jacobi.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,31 +1,33 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_JACOBI_HPP
-#define BOOST_MP_MATH_MP_INT_JACOBI_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_JACOBI_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_JACOBI_HPP
 
 
 namespace boost {
 namespace mp_math {
+namespace detail {
 
 // 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)
+template<class ApInt>
+int jacobi(const ApInt& a, const ApInt& p)
 {
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::size_type size_type;
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::size_type size_type;
 
   if (p <= digit_type(0))
     throw std::domain_error("jacobi: p must be greater than 0");
 
+ std::cout << "a = "; a.print();
+ std::cout << "p = "; p.print();
   if (!a)
     return 0;
-
+
   if (a == digit_type(1))
     return 1;
 
@@ -33,19 +35,19 @@
   int s = 0;
 
   // write a = a1 * 2**k
- mp_int<A,T> a1(a);
+ ApInt a1(a);
 
   // find largest power of two that divides a1
- const size_type k = a1.count_lsb();
+ const size_type k = a1.count_trailing_zero_bits();
   // now divide by it
- a1.shift_right(k,0);
+ a1 >>= k;
 
   // if k is even set s=1
   if ((k & 1) == 0)
     s = 1;
   else
   {
- // calculate p.digits_[0] mod 8
+ // calculate p[0] mod 8
     const digit_type residue = p[0] & 7;
 
     if (residue == 1 || residue == 7)
@@ -58,16 +60,15 @@
   if (((p[0] & 3) == 3) && ((a1[0] & 3) == 3))
     s = -s;
 
+ std::cout << "a1 = "; a1.print();
   if (a1 == digit_type(1))
     return s;
   else
- {
- const mp_int<A,T> p1(p % a1);
- return s * jacobi(p1, a1);
- }
+ return s * jacobi(p % a1, a1);
 }
 
 
+} // namespace detail
 } // namespace mp_math
 } // namespace boost
 

Copied: sandbox/mp_math/boost/mp_math/integer/detail/lcm.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/lcm.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,45 +1,69 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_LCM_HPP
-#define BOOST_MP_MATH_MP_INT_LCM_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_LCM_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_LCM_HPP
 
 
 namespace boost {
 namespace mp_math {
+namespace detail {
+
+// compute least common multiple as |a*b|/gcd(a,b)
+
+template<class ApInt, bool IsSigned = ApInt::is_signed>
+struct lcm_finder;
 
-// computes least common multiple as |a*b|/gcd(a,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 ApInt>
+struct lcm_finder<ApInt, false>
+{
+ static void lcm(ApInt& z, const ApInt& a, const ApInt& b);
+};
+
+
+template<class ApInt>
+void lcm_finder<ApInt, false>::lcm(ApInt& z, const ApInt& a, const ApInt& b)
 {
- mp_int<A,T> result;
-
   if (!a || !b)
   {
- result.zero();
- return result;
+ z = typename ApInt::digit_type(0);
+ return;
   }
-
- result = a / gcd(a, b) * b;
 
- result.set_sign(1);
-
- return result;
+ const ApInt u(a);
+ const ApInt v(b);
+
+ z = u / gcd(u, v) * v;
 }
 
-#ifdef BOOST_HAS_VARIADIC_TMPL
-template<class A, class T, class... MpInts>
-mp_int<A,T> lcm(const mp_int<A,T>& a, const mp_int<A,T>& b, const MpInts&... args)
+
+template<class ApInt>
+struct lcm_finder<ApInt, true>
 {
- return lcm(lcm(a, b), args...);
+ static void lcm(ApInt& z, const ApInt& a, const ApInt& b);
+};
+
+
+template<class ApInt>
+void lcm_finder<ApInt, true>::lcm(ApInt& z, const ApInt& a, const ApInt& b)
+{
+ if (!a || !b)
+ {
+ z = typename ApInt::digit_type(0);
+ return;
+ }
+
+ const ApInt u = abs(a);
+ const ApInt v = abs(b);
+
+ z = u / gcd(u, v) * v;
 }
-#endif
 
 
+} // namespace detail
 } // namespace mp_math
 } // namespace boost
 

Modified: sandbox/mp_math/boost/mp_math/integer/detail/meta_math.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/meta_math.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/meta_math.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,4 +1,4 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -14,7 +14,7 @@
 
 
 // power -----------------------------------------------------------------------
-
+/*
 template<
         typename IntegralT,
         IntegralT X, IntegralT Y,
@@ -40,7 +40,7 @@
 struct power
 {
         static const IntegralT value = power_impl<IntegralT,X,Y>::value;
-};
+};*/
 
 
 

Modified: sandbox/mp_math/boost/mp_math/integer/detail/modinv.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/modinv.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/modinv.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,67 +1,98 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_DETAIL_MODINV_HPP
-#define BOOST_MP_MATH_MP_INT_DETAIL_MODINV_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_MODINV_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_MODINV_HPP
 
+#include <boost/mp_math/integer/detail/base/divider.hpp>
 
 namespace boost {
 namespace mp_math {
 namespace detail {
 
-// hac 14.61, pp608
-template<class A1, class T>
-mp_int<A1,T> even_modinv(const mp_int<A1,T>& z, const mp_int<A1,T>& m)
+
+template<class ApInt>
+struct modular_inverter
+{
+ typedef typename ApInt::digit_type digit_type;
+ typedef base::divider<ApInt> base_divider_type;
+
+ static void modinv (ApInt& z, const ApInt& x, const ApInt& m);
+ static void even_modinv(ApInt& z, const ApInt& x, const ApInt& m);
+ static void odd_modinv (ApInt& z, const ApInt& x, const ApInt& m);
+};
+
+
+// returns the modular multiplicative inverse z of x (mod m) such that
+// z * x = 1 (mod m) =>
+// x^-1 = z (mod m)
+// The inverse exists only if a and m are coprime (i.e. gcd(a,m) = 1).
+// If no inverse exists this function will throw std::domain_error.
+template<class ApInt>
+void
+modular_inverter<ApInt>::modinv(ApInt& z, const ApInt& x, const ApInt& m)
 {
- typedef typename mp_int<A1,T>::digit_type digit_type;
+ if (m.is_negative())
+ throw std::domain_error("modinv: modulus is negative");
+ if (!m)
+ throw std::domain_error("modinv: modulus is zero");
+
+ // if the modulus is odd we can use a faster routine
+ if (m.is_odd())
+ odd_modinv(z, x, m);
+ else
+ even_modinv(z, x, m);
+}
 
+// HAC 14.61, pp608
+template<class ApInt>
+void
+modular_inverter<ApInt>::even_modinv(ApInt& z, const ApInt& x, const ApInt& m)
+{
   assert(m.is_even());
 
- static const char* const err_msg = "mp_int::modinv: inverse does not exist";
+ static const char* const err_msg = "modinv: inverse does not exist";
+
+ const ApInt y = x % m;
 
- const mp_int<A1,T> x = z % m;
-
- if (x.is_even())
+ if (y.is_even())
     throw std::domain_error(err_msg);
 
- mp_int<A1,T> u(x);
- mp_int<A1,T> v(m);
- mp_int<A1,T> A = digit_type(1);
- mp_int<A1,T> B = digit_type(0);
- mp_int<A1,T> C = digit_type(0);
- mp_int<A1,T> D = digit_type(1);
+ ApInt u(y);
+ ApInt v(m);
+ ApInt A = digit_type(1);
+ ApInt B = digit_type(0);
+ ApInt C = digit_type(0);
+ ApInt D = digit_type(1);
 
 top:
   while (u.is_even())
   {
- u.divide_by_2();
-
+ base_divider_type::divide_by_2(u);
+
     if (A.is_odd() || B.is_odd())
     {
- // A = (A+m)/2, B = (B-x)/2
       A += m;
- B -= x;
+ B -= y;
     }
- A.divide_by_2();
- B.divide_by_2();
+ base_divider_type::divide_by_2(A);
+ base_divider_type::divide_by_2(B);
   }
 
   while (v.is_even())
   {
- v.divide_by_2();
+ base_divider_type::divide_by_2(v);
 
     if (C.is_odd() || D.is_odd())
     {
- // C = (C+m)/2, D = (D-x)/2
       C += m;
- D -= x;
+ D -= y;
     }
- C.divide_by_2();
- D.divide_by_2();
+ base_divider_type::divide_by_2(C);
+ base_divider_type::divide_by_2(D);
   }
 
   if (u >= v)
@@ -87,66 +118,64 @@
     throw std::domain_error(err_msg);
 
   // if it's too low
- while (C.compare_to_digit(0) == -1)
+ while (C.is_negative())
     C += m;
-
+
   // too big
- while (C.compare_magnitude(m) != -1)
+ while (compare_magnitude(C, m) != -1)
     C -= m;
-
- return C;
+
+ swap(z, C);
 }
 
-/* computes the modular inverse via binary extended euclidean algorithm,
- * that is z = 1 / z mod m
- *
- * Based on even modinv except this is optimized for the case where m is
- * odd as per HAC Note 14.64 on pp. 610
- */
-template<class A1, class T>
-mp_int<A1,T> odd_modinv(const mp_int<A1,T>& z, const mp_int<A1,T>& m)
+// computes the modular inverse via binary extended euclidean algorithm,
+// that is z = 1 / z mod m
+//
+// Based on even modinv except this is optimized for the case where m is
+// odd as per HAC Note 14.64 on pp. 610
+template<class ApInt>
+void
+modular_inverter<ApInt>::odd_modinv(ApInt& z, const ApInt& x, const ApInt& m)
 {
- typedef typename mp_int<A1,T>::digit_type digit_type;
-
   assert(m.is_odd());
 
   // m == modulus, y == value to invert
   // we need y = |a|
- const mp_int<A1,T> y = z % m;
+ const ApInt y = x % m;
 
- mp_int<A1,T> u(m);
- mp_int<A1,T> v(y);
- mp_int<A1,T> A = digit_type(1);
- mp_int<A1,T> B = digit_type(0);
- mp_int<A1,T> C = digit_type(0);
- mp_int<A1,T> D = digit_type(1);
+ ApInt u(m);
+ ApInt v(y);
+ ApInt A = digit_type(1);
+ ApInt B = digit_type(0);
+ ApInt C = digit_type(0);
+ ApInt D = digit_type(1);
 
 top:
   while (u.is_even())
   {
- u.divide_by_2();
-
+ base_divider_type::divide_by_2(u);
+
     if (B.is_odd())
       B -= m;
-
- B.divide_by_2();
+
+ base_divider_type::divide_by_2(B);
   }
 
   while (v.is_even())
   {
- v.divide_by_2();
+ base_divider_type::divide_by_2(v);
 
     if (D.is_odd())
- D -= m;
+ D -= m;
 
- D.divide_by_2();
+ base_divider_type::divide_by_2(D);
   }
 
   if (u >= v)
   {
- /* u = u - v, B = B - D */
+ // u = u - v, B = B - D
     u -= v;
- B -=D;
+ B -= D;
   }
   else
   {
@@ -157,15 +186,15 @@
   if (u)
     goto top;
 
- /* now a = C, m = D, gcd == g*v */
+ // now a = C, m = D, gcd == g*v
 
   if (v != digit_type(1))
- throw std::domain_error("mp_int::modinv: inverse does not exist");
+ throw std::domain_error("modinv: inverse does not exist");
 
   while (D.is_negative())
     D += m;
 
- return D;
+ swap(z, D);
 }
 
 

Modified: sandbox/mp_math/boost/mp_math/integer/detail/modpow.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/modpow.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/modpow.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,31 +1,289 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_MODPOW_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_MODPOW_HPP
 
-#ifndef BOOST_MP_MATH_MP_INT_DETAIL_MODPOW_HPP
-#define BOOST_MP_MATH_MP_INT_DETAIL_MODPOW_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-#include <boost/mp_math/mp_int/detail/modular_reduction.hpp>
+#include <boost/mp_math/integer/detail/modular_reduction.hpp>
 
 namespace boost {
 namespace mp_math {
 namespace detail {
 
 
-template<class A, class T>
-mp_int<A,T> barret_modpow(const mp_int<A,T>& base,
- const mp_int<A,T>& exp,
- const mp_int<A,T>& m,
- int redmode,
- mp_int<A,T>& mu)
+// modpow_ctx allows us to precalculate and store certain values so that modpow
+// calls with the same modulus are sped up. We should probably store a pointer
+// value to the original modulus value here and then assert that we are handed
+// the same modulus in subsequent invocations.
+
+template<class ApInt>
+struct modpow_ctx
+{
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::size_type size_type;
+ typedef typename ApInt::traits_type traits_type;
+
+ // dr means diminished radix
+ enum modulus_type_t
+ { // R is our radix
+ mod_restricted_dr, // m = R^k - d; d <= R
+ mod_unrestricted_dr, // m = 2^k - d; d <= R
+ mod_unrestricted_dr_slow, // m = 2^k - d; d < d^(k/2)
+ mod_odd,
+ mod_generic
+ }modulus_type;
+
+ modpow_ctx() : precalculated(false) {}
+
+ modulus_type_t do_detect(const ApInt& m) const;
+
+ void detect_modulus_type(const ApInt& m)
+ {
+ modulus_type = do_detect(m);
+ }
+
+ void precalculate(const ApInt& m);
+
+ ApInt mu;
+ digit_type rho;
+ bool precalculated;
+};
+
+
+template<class ApInt>
+typename modpow_ctx<ApInt>::modulus_type_t
+modpow_ctx<ApInt>::do_detect(const ApInt& m) const
 {
- typedef typename mp_int<A,T>::size_type size_type;
- typedef typename mp_int<A,T>::size_type digit_type;
+ if (m.size() == 1)
+ return mod_unrestricted_dr;
+
+ size_type count = 0;
+
+ const size_type bits = m.precision() % traits_type::radix_bits;
 
- void (*redux)(mp_int<A,T>&, const mp_int<A,T>&, const mp_int<A,T>&);
+ if (!bits && m[m.size()-1] == traits_type::max_digit_value)
+ ++count;
+
+ for (typename ApInt::const_reverse_iterator d = m.rbegin() + 1;
+ d != m.rend(); ++d)
+ {
+ if (*d != traits_type::max_digit_value)
+ break;
+ else
+ ++count;
+ }
+
+ // if all bits are set
+ if (count == m.size() - 1)
+ return mod_restricted_dr;
+
+ // if all bits until the most significant digit are set
+ if (count == m.size() - 2)
+ {
+ bool all_bits_set = true;
+
+ // handle the remaining bits in the most significant digit
+ digit_type mask = 1;
+ for (size_type i = 0; i < bits; ++i)
+ {
+ if ((m[m.size()-1] & mask) == 0)
+ {
+ all_bits_set = false;
+ break;
+ }
+ mask <<= 1;
+ }
+ if (all_bits_set)
+ return mod_unrestricted_dr;
+ }
+
+ // if more than half of the bits are set
+ if (count >= m.size() / 2)
+ return mod_unrestricted_dr_slow;
+
+ if (m.is_odd())
+ return mod_odd;
+
+ return mod_generic;
+}
+
+template<class ApInt>
+void modpow_ctx<ApInt>::precalculate(const ApInt& m)
+{
+ switch (modulus_type)
+ {
+ case mod_restricted_dr:
+ {
+ rho = traits_type::max_digit_value - m[0] + 1U;
+ break;
+ }
+ case mod_unrestricted_dr:
+ {
+ const size_type p = m.precision();
+
+ ApInt tmp;
+ power<ApInt>::pow2(tmp, p);
+ base::adder<ApInt>::subtract_smaller_magnitude(tmp, m);
+
+ rho = tmp[0];
+ break;
+ }
+ case mod_unrestricted_dr_slow:
+ {
+ ApInt tmp;
+
+ power<ApInt>::pow2(tmp, m.precision());
+ mu = tmp - m;
+ break;
+ }
+ case mod_odd:
+ {
+ assert(m.is_odd());
+
+ // 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 = m[0];
+
+ static const size_type S = std::numeric_limits<digit_type>::digits;
+
+ 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
+ rho = traits_type::max_digit_value - x + 1U;
+ break;
+ }
+ case mod_generic:
+ {
+ // mu = b^2k/m
+ power<ApInt>::pow2(mu, m.size() * 2 * traits_type::digit_bits);
+ mu /= m;
+ break;
+ }
+ }
+
+ precalculated = true;
+}
+
+
+template<class ApInt>
+struct modular_power
+{
+ typedef typename ApInt::size_type size_type;
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::traits_type traits_type;
+
+ // computes z = base^exp % m
+ static void modpow(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& m,
+ modpow_ctx<ApInt>* ctx);
+
+ static void modpow_with_ctx(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& m,
+ const modpow_ctx<ApInt>& ctx);
+
+ static void barret_modpow(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& m,
+ int redmode,
+ const ApInt& mu);
+
+ static void montgomery_modpow(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& m,
+ int redmode,
+ digit_type mp);
+};
+
+
+template<class ApInt>
+void modular_power<ApInt>::modpow(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& mod,
+ modpow_ctx<ApInt>* ctx = 0)
+{
+ if (mod.is_negative())
+ throw std::domain_error("modpow: modulus must be positive");
+
+ if (exp.is_negative())
+ {
+ //modpow(z, modinv(base, mod), abs(exp), mod, ctx);
+ return;
+ }
+
+ if (!ctx)
+ {
+ modpow_ctx<ApInt> tmp_ctx;
+ tmp_ctx.detect_modulus_type(mod);
+ tmp_ctx.precalculate(mod);
+ modpow_with_ctx(z, base, exp, mod, tmp_ctx);
+ }
+ else
+ {
+ if (!ctx->precalculated)
+ {
+ ctx->detect_modulus_type(mod);
+ ctx->precalculate(mod);
+ }
+ modpow_with_ctx(z, base, exp, mod, *ctx);
+ }
+}
+
+template<class ApInt>
+void modular_power<ApInt>::modpow_with_ctx(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& mod,
+ const modpow_ctx<ApInt>& ctx)
+{
+ typedef modpow_ctx<ApInt> ctx_t;
+
+ switch (ctx.modulus_type)
+ {
+ case ctx_t::mod_restricted_dr:
+ montgomery_modpow(z, base, exp, mod, 1, ctx.rho); break;
+ case ctx_t::mod_unrestricted_dr:
+ montgomery_modpow(z, base, exp, mod, 2, ctx.rho); break;
+ case ctx_t::mod_unrestricted_dr_slow:
+ barret_modpow (z, base, exp, mod, 1, ctx.mu); break;
+ case ctx_t::mod_odd:
+ montgomery_modpow(z, base, exp, mod, 0, ctx.rho); break;
+ case ctx_t::mod_generic:
+ default:
+ barret_modpow (z, base, exp, mod, 0, ctx.mu); break;
+ }
+}
+
+template<class ApInt>
+void modular_power<ApInt>::barret_modpow(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& m,
+ int redmode,
+ const ApInt& mu)
+{
+ void (*redux)(ApInt&, const ApInt&, const ApInt&);
 
   // find window size
   const size_type x = exp.precision();
@@ -46,13 +304,13 @@
     winsize = 8;
 
   if (redmode == 0)
- redux = &barrett_reduce;
+ redux = &modular_reducer<ApInt>::barrett_reduce;
   else
- redux = &unrestricted_dr_slow_reduce;
+ redux = &modular_reducer<ApInt>::unrestricted_dr_slow_reduce;
 
   // The M table contains powers of the base, e.g. M[i] = base**i % m
   // The first half of the table is not computed though except for M[0] and M[1]
- mp_int<A,T> M[256];
+ ApInt M[256];
   M[1] = base % m;
 
   // compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times
@@ -61,7 +319,7 @@
   for (size_type i = 0; i < (winsize - 1); ++i)
   {
     const size_type offset = 1 << (winsize - 1);
- M[offset].sqr();
+ multiplier<ApInt>::sqr(M[offset]);
     // reduce modulo m
     (*redux)(M[offset], m, mu);
   }
@@ -77,12 +335,12 @@
   }
 
   // setup result
- mp_int<A,T> res = digit_type(1);
+ z = digit_type(1);
 
   int mode = 0;
   int bitcnt = 1;
   digit_type buf = 0;
- typename mp_int<A,T>::const_reverse_iterator exp_digit = exp.rbegin();
+ typename ApInt::const_reverse_iterator exp_digit = exp.rbegin();
   size_type bitcpy = 0;
   int bitbuf = 0;
 
@@ -93,14 +351,14 @@
     {
       if (exp_digit == exp.rend())
         break;
-
+
       // read next digit and reset the bitcnt
       buf = *exp_digit++;
- bitcnt = mp_int<A,T>::valid_bits;
+ bitcnt = traits_type::radix_bits;
     }
 
     // grab the next msb from the exponent
- int y = (buf >> static_cast<digit_type>(mp_int<A,T>::valid_bits - 1)) & 1;
+ int y = (buf >> static_cast<digit_type>(traits_type::radix_bits - 1)) & 1;
     buf <<= digit_type(1);
 
     // if the bit is zero and mode == 0 then we ignore it
@@ -113,8 +371,8 @@
     // if the bit is zero and mode == 1 then we square
     if (mode == 1 && y == 0)
     {
- res.sqr();
- (*redux)(res, m, mu);
+ multiplier<ApInt>::sqr(z);
+ (*redux)(z, m, mu);
       continue;
     }
 
@@ -128,13 +386,13 @@
       // square first
       for (size_type i = 0; i < winsize; ++i)
       {
- res.sqr();
- (*redux)(res, m, mu);
+ multiplier<ApInt>::sqr(z);
+ (*redux)(z, m, mu);
       }
 
       // then multiply
- res *= M[bitbuf];
- (*redux)(res, m, mu);
+ z *= M[bitbuf];
+ (*redux)(z, m, mu);
 
       // empty window and reset
       bitcpy = 0;
@@ -149,40 +407,35 @@
     // square then multiply if the bit is set
     for (size_type i = 0; i < bitcpy; ++i)
     {
- res.sqr();
- (*redux)(res, m, mu);
+ multiplier<ApInt>::sqr(z);
+ (*redux)(z, m, mu);
 
       bitbuf <<= 1;
       if ((bitbuf & (1 << winsize)) != 0)
       {
- res *= M[1];
- (*redux)(res, m, mu);
+ z *= M[1];
+ (*redux)(z, m, mu);
       }
     }
   }
-
- return 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>
-mp_int<A,T> montgomery_modpow(const mp_int<A,T>& base,
- const mp_int<A,T>& exp,
- const mp_int<A,T>& m,
- int redmode,
- typename mp_int<A,T>::digit_type mp)
+// 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 ApInt>
+void modular_power<ApInt>::montgomery_modpow(ApInt& z,
+ const ApInt& base,
+ const ApInt& exp,
+ const ApInt& m,
+ int redmode,
+ digit_type mp)
 {
- typedef typename mp_int<A,T>::size_type size_type;
- typedef typename mp_int<A,T>::digit_type digit_type;
+ void (*redux)(ApInt&, const ApInt&, digit_type);
 
- void (*redux)(mp_int<A,T>&, const mp_int<A,T>&, digit_type);
-
   // find window size
   const size_type x = exp.precision();
   size_type winsize;
@@ -200,32 +453,28 @@
     winsize = 7;
   else
     winsize = 8;
-
- //digit_type mp = ctx->mp;
-
+
   if (redmode == 0)
- redux = &montgomery_reduce;
+ redux = &modular_reducer<ApInt>::montgomery_reduce;
   else if (redmode == 1)
- redux = &restricted_dr_reduce;
+ redux = &modular_reducer<ApInt>::restricted_dr_reduce;
   else
- redux = &unrestricted_dr_reduce;
-
- mp_int<A,T> res;
+ redux = &modular_reducer<ApInt>::unrestricted_dr_reduce;
 
   // create M table
   // The first half of the table is not computed though except for M[0] and M[1]
- mp_int<A,T> M[256];
-
+ ApInt M[256];
+
   if (redmode == 0)
   {
     // now we need R mod m
- montgomery_normalize(res, m);
+ modular_reducer<ApInt>::montgomery_normalize(z, m);
     // now set M[1] to G * R mod m
- M[1] = (base * res) % m;
+ M[1] = (base * z) % m;
   }
   else
   {
- res = digit_type(1);
+ z = digit_type(1);
     M[1] = base % m;
   }
 
@@ -235,7 +484,7 @@
   for (size_type i = 0; i < (winsize - 1); ++i)
   {
     const size_type offset = 1 << (winsize - 1);
- M[offset].sqr();
+ multiplier<ApInt>::sqr(M[offset]);
     (*redux)(M[offset], m, mp);
   }
 
@@ -243,15 +492,15 @@
   for (size_type i = (1 << (winsize - 1)) + 1;
        i < (size_type(1) << winsize); ++i)
   {
- M[i] = M[i-1] * M[1];
+ multiplier<ApInt>::mul(M[i], M[i-1], M[1]);
     (*redux)(M[i], m, mp);
   }
 
- /* set initial mode and bit cnt */
+ // set initial mode and bit cnt
   int mode = 0;
   int bitcnt = 1;
   digit_type buf = 0;
- typename mp_int<A,T>::const_reverse_iterator exp_digit = exp.rbegin();
+ typename ApInt::const_reverse_iterator exp_digit = exp.rbegin();
   size_type bitcpy = 0;
   unsigned int bitbuf = 0;
 
@@ -264,11 +513,11 @@
         break;
       // read next digit and reset bitcnt
       buf = *exp_digit++;
- bitcnt = mp_int<A,T>::valid_bits;
+ bitcnt = traits_type::radix_bits;
     }
 
     // grab the next msb from the exponent
- int y = (buf >> (mp_int<A,T>::valid_bits - 1)) & 1;
+ int y = (buf >> (traits_type::radix_bits - 1)) & 1;
     buf <<= digit_type(1);
 
     // if the bit is zero and mode == 0 then we ignore it
@@ -281,8 +530,8 @@
     // if the bit is zero and mode == 1 then we square
     if (mode == 1 && y == 0)
     {
- res.sqr();
- (*redux)(res, m, mp);
+ multiplier<ApInt>::sqr(z);
+ (*redux)(z, m, mp);
       continue;
     }
 
@@ -293,16 +542,14 @@
     if (bitcpy == winsize)
     {
       // ok window is filled so square as required and multiply
- // square first
       for (size_type i = 0; i < winsize; ++i)
       {
- res.sqr();
- (*redux)(res, m, mp);
+ multiplier<ApInt>::sqr(z);
+ (*redux)(z, m, mp);
       }
 
- // then multiply
- res *= M[bitbuf];
- (*redux)(res, m, mp);
+ z *= M[bitbuf];
+ (*redux)(z, m, mp);
 
       // empty window and reset
       bitcpy = 0;
@@ -314,19 +561,17 @@
   // if bits remain then square/multiply
   if (mode == 2 && bitcpy > 0)
   {
- // square then multiply if the bit is set
     for (size_type i = 0; i < bitcpy; ++i)
     {
- res.sqr();
- (*redux)(res, m, mp);
+ multiplier<ApInt>::sqr(z);
+ (*redux)(z, m, mp);
 
       // get next bit of the window
       bitbuf <<= 1;
       if ((bitbuf & (1 << winsize)) != 0)
       {
- // then multiply
- res *= M[1];
- (*redux)(res, m, mp);
+ z *= M[1];
+ (*redux)(z, m, mp);
       }
     }
   }
@@ -335,9 +580,7 @@
   // 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)
- (*redux)(res, m, mp);
-
- return res;
+ (*redux)(z, m, mp);
 }
 
 

Modified: sandbox/mp_math/boost/mp_math/integer/detail/modular_reduction.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/modular_reduction.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/modular_reduction.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,76 +1,108 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_DETAIL_MODULAR_REDUCTION_HPP
-#define BOOST_MP_MATH_MP_INT_DETAIL_MODULAR_REDUCTION_HPP
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_MODULAR_REDUCTION_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_MODULAR_REDUCTION_HPP
 
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#include <boost/mp_math/integer/detail/adder.hpp>
+#include <boost/mp_math/integer/detail/multiplier.hpp>
+#include <boost/mp_math/integer/detail/power.hpp>
+#include <boost/mp_math/integer/detail/shifter.hpp>
 
 namespace boost {
 namespace mp_math {
 namespace detail {
 
-// reduces x mod m, assumes 0 < x < m**2, mu is precomputed.
-// From HAC pp.604 Algorithm 14.42
-template<class A, class T>
-void barrett_reduce(mp_int<A,T>& x, const mp_int<A,T>& m, const mp_int<A,T>& mu)
+template<class ApInt>
+int compare_magnitude(const ApInt& lhs, const ApInt& rhs)
+{
+ return ApInt::traits_type::ops_type::compare_magnitude(
+ lhs.digits(), lhs.size(), rhs.digits(), rhs.size());
+}
+
+
+template<class ApInt>
+struct modular_reducer
 {
- typedef typename mp_int<A,T>::digit_type digit_type;
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::size_type size_type;
+ typedef typename ApInt::traits_type traits_type;
+ typedef typename traits_type::ops_type ops_type;
+
+ static void barrett_reduce (ApInt& z, const ApInt& m, const ApInt& mu);
+ static void montgomery_reduce (ApInt& z, const ApInt& m, digit_type rho);
+ static void montgomery_normalize (ApInt& z, const ApInt& n);
+ static void restricted_dr_reduce (ApInt& z, const ApInt& n, digit_type k);
+ static void unrestricted_dr_reduce(ApInt& z, const ApInt& n, digit_type d);
+ static void unrestricted_dr_slow_reduce(ApInt& z, const ApInt& n, const ApInt& d);
+};
+
 
- const typename mp_int<A,T>::size_type k = m.size();
+// reduces x mod m, assumes 0 < x < m^2, mu is precomputed.
+// From HAC pp.604 Algorithm 14.42
+template<class ApInt>
+void modular_reducer<ApInt>::
+barrett_reduce(ApInt& x, const ApInt& m, const ApInt& mu)
+{
+ size_type k = m.size();
 
- mp_int<A,T> q(x);
+ ApInt q(x);
 
- // q = x / base**(k-1)
- q.shift_digits_right(k - 1);
+ // q = x / radix^(k-1)
+ shifter<ApInt>::shift_digits_right(q, k-1);
 
   // according to HAC this optimization is ok
- if (k > digit_type(1) << (mp_int<A,T>::valid_bits - 1))
+ if (k > digit_type(1) << (traits_type::radix_bits - 1))
     q *= mu;
   else
- q.fast_mul_high_digits(mu, k);
+ {
+ //q.fast_mul_high_digits(mu, k);
+ ApInt tmp; tmp.reserve(k);
+ ops_type::comba_mul_hi(tmp.digits(), q.digits(), q.size(),
+ m.digits(), m.size(), k);
+ swap(tmp, q);
+ }
 
- // q = q / base**(k+1)
- q.shift_digits_right(k + 1);
+ // q = q / radix^(k+1)
+ shifter<ApInt>::shift_digits_right(q, k+1);
 
- // r = x mod base**(k+1)
- x.modulo_2_to_the_power_of(mp_int<A,T>::valid_bits * (k + 1));
+ // r = x mod radix^(k+1)
+ base::divider<ApInt>::modulo_pow2(x, traits_type::radix_bits * (k + 1));
 
- // q = q * m mod base**(k+1)
- q.mul_digits(m, k + 1);
+ // q = q * m mod radix^(k+1)
+ //q.mul_digits(m, k + 1);
+ ApInt tmp; tmp.reserve(k + 1);
+ ops_type::comba_mul_lo(tmp.digits(), q.digits(), q.size(),
+ m.digits(), m.size(), k + 1);
+ swap(tmp, q);
 
   x -= q;
 
- // If x < 0, add base**(k+1) to it
+ // if x < 0, add radix^(k+1) to it
   if (x.is_negative())
   {
     q = digit_type(1);
- q.shift_digits_left(k + 1);
+ shifter<ApInt>::shift_digits_left(q, k+1);
     x += q;
   }
 
   while (x >= m)
- x.sub_smaller_magnitude(m);
+ base::adder<ApInt>::subtract_smaller_magnitude(x, m);
 }
 
-/* computes xR**-1 == x (mod m) via Montgomery Reduction */
-template<class A, class T>
-void montgomery_reduce(mp_int<A,T>& x,
- const mp_int<A,T>& m,
- typename mp_int<A,T>::digit_type rho)
+// computes xR^-1 == x (mod m) via Montgomery Reduction
+template<class ApInt>
+void modular_reducer<ApInt>::
+montgomery_reduce(ApInt& x, const ApInt& m, digit_type rho)
 {
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::word_type word_type;
- typedef typename mp_int<A,T>::size_type size_type;
- typedef typename mp_int<A,T>::iterator iterator;
- typedef typename mp_int<A,T>::const_iterator const_iterator;
-
   const size_type num = m.size() * 2 + 1;
 
- x.grow_capacity(num);
- std::memset(x.digits() + x.size(), 0, (x.capacity() - x.size()) * sizeof(digit_type));
+ x.reserve(num);
+ std::memset(x.digits() + x.size(), 0,
+ (x.capacity() - x.size()) * sizeof(digit_type));
   x.set_size(num);
 
   for (size_type i = 0; i < m.size(); ++i)
@@ -80,62 +112,59 @@
     // this allows multiply_add_digits to reduce the input one digit at a time.
     const digit_type mu = x[i] * rho;
 
- // x = x + mu * m * base**i
-
+ // x = x + mu * m * base^i
+
     digit_type carry =
- mp_int<A,T>::ops_type::multiply_add_digits(x.digits() + i,
- m.digits(),
- mu,
- x.digits() + i,
- m.size());
+ ops_type::multiply_add_digits(x.digits() + i,
+ m.digits(),
+ mu,
+ m.size());
 
     // At this point the i'th digit of x should be zero
 
- mp_int<A,T>::ops_type::ripple_carry(x.digits() + i + m.size(),
- x.digits() + i + m.size(),
- num,
- carry);
+ ops_type::ripple_carry(x.digits() + i + m.size(),
+ x.digits() + i + m.size(), num, carry);
   }
 
- // at this point the m.size least significant digits of x are all zero which
- // means we can shift x to the right by m.size digits and the residue is
- // unchanged.
-
- // x = x/base**m.size()
   x.clamp();
 
   if (!x)
- x.set_sign(1);
+ x.set_sign_bit(0);
 
- x.shift_digits_right(m.size());
+ // at this point the m.size least significant digits of x are all zero which
+ // means we can shift x to the right by m.size digits and the residue is
+ // unchanged.
 
- if (x.compare_magnitude(m) != -1)
- x.sub_smaller_magnitude(m);
+ // x = x/radix^m.size()
+ shifter<ApInt>::shift_digits_right(x, m.size());
+
+ if (compare_magnitude(x, m) != -1)
+ base::adder<ApInt>::subtract_smaller_magnitude(x, m);
 }
 
 // shifts with subtractions when the result is greater than n.
 // The method is slightly modified to shift B unconditionally upto just under
 // the leading bit of n. This saves alot of multiple precision shifting.
-template<class A, class T>
-void montgomery_normalize(mp_int<A,T>& x, const mp_int<A,T>& n)
+template<class ApInt>
+void modular_reducer<ApInt>::montgomery_normalize(ApInt& x, const ApInt& n)
 {
   // how many bits of last digit does n use
- typename mp_int<A,T>::size_type bits = n.precision() % mp_int<A,T>::valid_bits;
+ size_type bits = n.precision() % traits_type::radix_bits;
 
   if (n.size() > 1)
- x.pow2((n.size() - 1) * mp_int<A,T>::valid_bits + bits - 1);
+ power<ApInt>::pow2(x, (n.size() - 1) * traits_type::radix_bits + bits - 1);
   else
   {
- x = typename mp_int<A,T>::digit_type(1);
+ x = digit_type(1);
     bits = 1;
   }
 
   // now compute C = A * B mod n
- for (int i = bits - 1; i < mp_int<A,T>::valid_bits; ++i)
+ for (size_type i = bits; i <= traits_type::radix_bits; ++i)
   {
- x.multiply_by_2();
- if (x.compare_magnitude(n) != -1)
- x.sub_smaller_magnitude(n);
+ multiplier<ApInt>::multiply_by_2(x);
+ if (compare_magnitude(x, n) != -1)
+ base::adder<ApInt>::subtract_smaller_magnitude(x, n);
   }
 }
 
@@ -151,36 +180,23 @@
 // 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
-template<class A, class T>
-void restricted_dr_reduce(mp_int<A,T>& x,
- const mp_int<A,T>& n,
- typename mp_int<A,T>::digit_type k)
+template<class ApInt>
+void modular_reducer<ApInt>::
+restricted_dr_reduce(ApInt& x, const ApInt& n, digit_type k)
 {
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::word_type word_type;
- typedef typename mp_int<A,T>::size_type size_type;
- typedef typename mp_int<A,T>::iterator iterator;
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::size_type size_type;
+ typedef typename ApInt::iterator iterator;
 
   const size_type m = n.size();
 
- x.grow_capacity(m + m);
+ x.reserve(m + m);
   std::memset(x.digits() + x.size(), 0, (m + m - x.size()) * sizeof(digit_type));
 
 top:
- // set carry to zero
- digit_type mu = 0;
-
- // compute (r mod B**m) + k * [r/B**m] inline and inplace
- for (iterator d = x.begin(); d != x.begin() + m; ++d)
- {
- const word_type r = static_cast<word_type>(*(d + m))
- * static_cast<word_type>(k) + *d + mu;
- *d = static_cast<digit_type>(r);
- mu = static_cast<digit_type>(r >> static_cast<word_type>(mp_int<A,T>::digit_bits));
- }
 
- // set final carry
- x[m] = mu;
+ // compute (r mod B**m) + k * [r/B**m]
+ x[m] = ops_type::multiply_add_digits(x.digits(), x.digits() + m, k, m);
 
   // zero words above m
   if (x.size() > m + 1) // guard against overflow
@@ -189,70 +205,69 @@
   x.clamp();
 
   if (!x)
- x.set_sign(1);
+ x.set_sign_bit(0);
 
- if (x.compare_magnitude(n) != -1)
+ if (compare_magnitude(x, n) != -1)
   {
- x.sub_smaller_magnitude(n);
+ base::adder<ApInt>::subtract_smaller_magnitude(x, n);
     goto top;
   }
 }
 
-// reduces x modulo n where n is of the form 2**p - d
-template<class A, class T>
-void unrestricted_dr_reduce(mp_int<A,T>& x,
- const mp_int<A,T>& n,
- typename mp_int<A,T>::digit_type d)
+// reduces x modulo n where n is of the form 2^p - d
+template<class ApInt>
+void modular_reducer<ApInt>::
+unrestricted_dr_reduce(ApInt& x, const ApInt& n, digit_type d)
 {
- const typename mp_int<A,T>::size_type p = n.precision();
+ const size_type p = n.precision();
 
 top:
 
- mp_int<A,T> q(x);
-
- /* q = a/2**p, r = r mod 2**p */
- q.shift_right(p, &x);
-
- if (d != 1)
- q.multiply_by_digit(d);
-
- x.add_magnitude(q);
+ ApInt q(x);
+
+ // q = x/2^p, x = x % 2^p
+ shifter<ApInt>::shift_bits_right(q, x, p);
+
+ q *= d;
 
- if (x.compare_magnitude(n) != -1)
+ adder<ApInt>::add_magnitude(x, q);
+
+ if (compare_magnitude(x, n) != -1)
   {
- x.sub_smaller_magnitude(n);
+ base::adder<ApInt>::subtract_smaller_magnitude(x, n);
     goto top;
   }
 }
 
-// reduces x modulo n where n is of the form 2**p - d. This differs from
+// reduces x modulo n where n is of the form 2^p - d. This differs from
 // unrestricted_dr_reduce since "d" can be larger than a single digit.
-template<class A, class T>
-void unrestricted_dr_slow_reduce(mp_int<A,T>& x,
- const mp_int<A,T>& n,
- const mp_int<A,T>& d)
+template<class ApInt>
+void modular_reducer<ApInt>::
+unrestricted_dr_slow_reduce(ApInt& x, const ApInt& n, const ApInt& d)
 {
- const typename mp_int<A,T>::size_type p = n.precision();
+ const size_type p = n.precision();
 
 top:
 
- mp_int<A,T> q(x);
+ ApInt q(x);
 
- // q = x/2**p, r = r mod 2**p
- q.shift_right(p, &x);
+ // q = x/2^p, x = x % 2^p
+ shifter<ApInt>::shift_bits_right(q, x, p);
 
   q *= d;
 
- x.add_magnitude(q);
+ adder<ApInt>::add_magnitude(x, q);
 
- if (x.compare_magnitude(n) != -1)
+ if (compare_magnitude(x, n) != -1)
   {
- x.sub_smaller_magnitude(n);
+ base::adder<ApInt>::subtract_smaller_magnitude(x, n);
     goto top;
   }
 }
 
 
+
+
 } // namespace detail
 } // namespace mp_math
 } // namespace boost

Copied: sandbox/mp_math/boost/mp_math/integer/detail/multiplier.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/mul.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/mul.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/multiplier.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,135 +1,339 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-// multiplies by a single digit
-template<class A, class T>
-void mp_int<A,T>::multiply_by_digit(digit_type x)
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_MULTIPLIER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_MULTIPLIER_HPP
+
+#include <boost/mp_math/integer/detail/shifter.hpp>
+#include <boost/mp_math/integer/detail/base/adder.hpp>
+#include <boost/mp_math/integer/detail/base/divider.hpp>
+#include <boost/mp_math/integer/detail/base/multiplier.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+template<
+ class ApInt,
+ bool IsSigned = ApInt::is_signed
+>
+struct multiplier;
+
+
+template<class ApInt>
+struct multiplier<ApInt, false>
 {
- if (x == 0)
+ typedef ApInt int_type;
+ typedef typename int_type::traits_type traits_type;
+ typedef typename traits_type::ops_type ops_type;
+ typedef typename int_type::digit_type digit_type;
+ typedef typename int_type::size_type size_type;
+ typedef shifter<int_type> shifter_type;
+ typedef base::adder<int_type> base_adder_type;
+ typedef base::divider<int_type> base_divider_type;
+ typedef base::multiplier<int_type> base_multiplier_type;
+
+ static void multiply_or_square(ApInt& z, const ApInt& x);
+ static void multiply_or_square(ApInt& z, const ApInt& x, const ApInt& y);
+
+ static void mul (ApInt& z, const ApInt& x, const ApInt& y);
+ static void long_mul (ApInt& z, const ApInt& x, const ApInt& y);
+ static void comba_mul (ApInt& z, const ApInt& x, const ApInt& y);
+ static void karatsuba_mul(ApInt& z, const ApInt& x, const ApInt& y);
+ static void toom3_mul (ApInt& z, const ApInt& x, const ApInt& y);
+
+ static void multiply_by_2(ApInt& z);
+
+ static void sqr (ApInt& z);
+ static void sqr (ApInt& z, const ApInt& x);
+ static void comba_sqr (ApInt& z, const ApInt& x);
+ static void karatsuba_sqr(ApInt& z, const ApInt& x);
+ static void toom3_sqr (ApInt& z, const ApInt& x);
+
+private:
+
+/* static void long_or_comba_mul(ApInt& z, const ApInt& x, const ApInt& y,
+ bool_<false>)
   {
- zero();
- return;
+ long_mul(z, x, y);
   }
- else if (x == 1)
- return;
 
- // make sure we can hold the result
- grow_capacity(size_ + 1);
-
- const digit_type carry =
- ops_type::multiply_by_digit(digits(), digits(), size(), x);
+ static void long_or_comba_mul(ApInt& z, const ApInt& x, const ApInt& y,
+ bool_<true>)
+ {
+ comba_mul(z, x, y);
+ }*/
+};
 
- if (carry)
- push(carry);
+
+template<class ApInt>
+void multiplier<ApInt, false>::multiply_or_square(ApInt& z, const ApInt& x)
+{
+ if (&z == &x)
+ sqr(z);
+ else
+ mul(z, z, x);
 }
 
-/* *this *= 2 */
-template<class A, class T>
-void mp_int<A,T>::multiply_by_2()
+template<class ApInt>
+void
+multiplier<ApInt, false>::
+multiply_or_square(ApInt& z, const ApInt& x, const ApInt& y)
 {
- grow_capacity(size_ + 1);
+ if (&x == &y)
+ sqr(z, x);
+ else
+ mul(z, x, y);
+}
 
- const digit_type carry =
- ops_type::multiply_by_two(digits(), digits(), size());
+template<class ApInt>
+void multiplier<ApInt, false>::mul(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ // always multiply larger by smaller number
+ const ApInt* a = &x;
+ const ApInt* b = &y;
+ if (a->size() < b->size())
+ std::swap(a, b);
 
- if (carry)
- push(carry);
+ if (b->size() == 1U)
+ {
+ if ((*b)[0] == 0U)
+ {
+ z.reserve(1);
+ z[0] = 0;
+ z.set_size(1);
+ }
+ else if ((*b)[0] == 1U)
+ z = *a;
+ else
+ ApInt::template integral_ops<digit_type>::multiply(z, *a, (*b)[0]);
+
+ return;
+ }
+
+ if (b->size() < traits_type::karatsuba_mul_threshold)
+ comba_mul(z, *a, *b);
+ else if (b->size() < traits_type::toom_mul_threshold)
+ karatsuba_mul(z, *a, *b);
+ else
+ toom3_mul(z, *a, *b);
 }
 
+template<class ApInt>
+inline
+void multiplier<ApInt, false>::
+long_mul(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ if ((&z != &x) && (&z != &y))
+ {
+ z.reserve(x.size() + y.size());
+ base_multiplier_type::long_mul(z, x, y);
+ }
+ else
+ {
+ ApInt tmp;
+ tmp.reserve(x.size() + y.size());
+ base_multiplier_type::long_mul(tmp, x, y);
+ swap(tmp, z);
+ }
+}
+
+template<class ApInt>
+inline
+void multiplier<ApInt, false>::
+comba_mul(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ if ((&z != &x) && (&z != &y))
+ {
+ z.reserve(x.size() + y.size());
+ base_multiplier_type::comba_mul(z, x, y);
+ }
+ else
+ {
+ ApInt tmp;
+ tmp.reserve(x.size() + y.size());
+ base_multiplier_type::comba_mul(tmp, x, y);
+ swap(tmp, z);
+ }
+}
+
+// Divide and conquer multiplication using the Karatsuba algorithm.
+//
+// Let B represent the radix [e.g. 2^radix_bits] and let n represent half of
+// the number of digits in 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 digits) 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 operator *
+// can end up back in this function if x0, x1, y0, or y1 are above the
+// threshold. This leads to O(N^lg(3)) or O(N^1.584) complexity. Generally
+// though the overhead of this method doesn't pay off until a certain size
+// (N ~ 80) is reached.
+template<class ApInt>
+void multiplier<ApInt, false>::
+karatsuba_mul(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ assert(x.size() >= y.size());
+
+ ApInt x0, x1, y0, y1, x0y0, x1y1;
+
+ // B is the point at which we split both numbers
+ const size_type B = y.size() / 2;
+
+ // allocate memory
+ x0.reserve(B);
+ x1.reserve(x.size() + y.size());
+ y0.reserve(B);
+ y1.reserve(y.size() - B + 1);
+
+ x0.set_size(B);
+ y0.set_size(B);
+ x1.set_size(x.size() - B);
+ y1.set_size(y.size() - B);
+
+ // copy digits over
+ static const size_type s = sizeof(digit_type);
+ std::memcpy(x0.digits(), x.digits(), s * B);
+ std::memcpy(y0.digits(), y.digits(), s * B);
+ std::memcpy(x1.digits(), x.digits() + B, s * (x.size() - B));
+ std::memcpy(y1.digits(), y.digits() + B, s * (y.size() - B));
+
+ x0.clamp();
+ y0.clamp();
+
+ // now evaluate the term
+ // x1y1 * B**2n + ((x1 + x0)(y1 + y0) - (x0y0 + x1y1)) * B + x0y0
+
+ mul(x0y0, x0, y0);
+ mul(x1y1, x1, y1);
+
+ // tmp = (x1 + x0) * (y1 + y0)
+ x1 += x0;
+ y1 += y0;
+ // we don't need a tmp just reuse x1
+ mul(x1, x1, y1);
+
+ // tmp -= (x0y0 + x1y1);
+ base_adder_type::subtract_smaller_magnitude(x1, x0y0);
+ base_adder_type::subtract_smaller_magnitude(x1, x1y1);
+
+ // shift by B
+ if (x1 != digit_type(0))
+ shifter_type::shift_digits_left(x1, B);
+ if (x1 != digit_type(0))
+ shifter_type::shift_digits_left(x1y1, B * 2);
+
+ x1y1 += x1;
+ x1y1 += x0y0;
+ z.swap(x1y1);
+}
 
-// multiplication using the Toom-Cook 3-way algorithm
+// 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
+// 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)
+template<class ApInt>
+void multiplier<ApInt, false>::
+toom3_mul(ApInt& z, const ApInt& x, const ApInt& y)
 {
- const size_type B = std::min(size_, b.size_) / 3;
-
+ assert(x.size() >= y.size());
+
+ const size_type B = y.size() / 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);
-
+ ApInt a0(x);
+ base_divider_type::modulo_pow2(a0, traits_type::radix_bits * B);
+ ApInt a1(x);
+ shifter_type::shift_digits_right(a1, B);
+ base_divider_type::modulo_pow2(a1, traits_type::radix_bits * B);
+ ApInt a2(x);
+ shifter_type::shift_digits_right(a2, 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);
+ ApInt b0(y);
+ base_divider_type::modulo_pow2(b0, traits_type::radix_bits * B);
+ ApInt b1(y);
+ shifter_type::shift_digits_right(b1, B);
+ base_divider_type::modulo_pow2(b1, traits_type::radix_bits * B);
+ ApInt b2(y);
+ shifter_type::shift_digits_right(b2, B*2);
 
   // w0 = a0*b0
- const mp_int w0(a0 * b0);
-
+ const ApInt w0(a0 * b0);
+
   // w4 = a2 * b2
- mp_int w4 = a2 * b2;
-
+ ApInt w4 = a2 * b2;
+
   // w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0))
- mp_int tmp1 = a0;
- tmp1.multiply_by_2();
+ ApInt tmp1 = a0;
+ multiply_by_2(tmp1);
   tmp1 += a1;
- tmp1.multiply_by_2();
+ multiply_by_2(tmp1);
   tmp1 += a2;
-
- mp_int tmp2 = b0;
- tmp2.multiply_by_2();
+
+ ApInt tmp2 = b0;
+ multiply_by_2(tmp2);
   tmp2 += b1;
- tmp2.multiply_by_2();
+ multiply_by_2(tmp2);
   tmp2 += b2;
 
- mp_int w1 = tmp1 * tmp2;
+ ApInt w1 = tmp1 * tmp2;
 
   // w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2))
   tmp1 = a2;
- tmp1.multiply_by_2();
+ multiply_by_2(tmp1);
   tmp1 += a1;
- tmp1.multiply_by_2();
+ multiply_by_2(tmp1);
   tmp1 += a0;
 
   tmp2 = b2;
- tmp2.multiply_by_2();
+ multiply_by_2(tmp2);
   tmp2 += b1;
- tmp2.multiply_by_2();
+ multiply_by_2(tmp2);
   tmp2 += b0;
 
- mp_int w3 = tmp1 * tmp2;
+ ApInt 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;
+ ApInt w2 = tmp1 * tmp2;
 
- // now solve the matrix
+ // 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
-
+ //
+ // 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();
+ base_divider_type::divide_by_2(w1);
   // r3/2
- w3.divide_by_2();
+ base_divider_type::divide_by_2(w3);
   // r2 - r0 - r4
   w2 -= w0;
   w2 -= w4;
@@ -144,7 +348,7 @@
   tmp1 = w4 << 3;
   w3 -= tmp1;
   // 3r2 - r1 - r3
- w2.multiply_by_digit(3);
+ w2 *= digit_type(3);
   w2 -= w1;
   w2 -= w3;
   // r1 - r2
@@ -152,210 +356,403 @@
   // r3 - r2
   w3 -= w2;
   // r1/3
- w1.divide_by_3();
+ base_divider_type::divide_by_3(w1);
   // r3/3
- w3.divide_by_3();
+ base_divider_type::divide_by_3(w3);
 
   // 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);
+ if (w1 != digit_type(0))
+ shifter_type::shift_digits_left(w1, 1 * B);
+ if (w2 != digit_type(0))
+ shifter_type::shift_digits_left(w2, 2 * B);
+ if (w3 != digit_type(0))
+ shifter_type::shift_digits_left(w3, 3 * B);
+ if (w4 != digit_type(0))
+ shifter_type::shift_digits_left(w4, 4 * B);
 
- *this = w0 + w1;
+ z = w0 + w1;
   tmp1 = w2 + w3;
   tmp1 += w4;
- *this += tmp1;
+ z += 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
+template<class ApInt>
+void multiplier<ApInt, false>::multiply_by_2(ApInt& z)
+{
+ z.reserve(z.size() + 1);
+
+ const digit_type carry =
+ ops_type::multiply_by_two(z.digits(), z.digits(), z.size());
+
+ if (carry)
+ z.push(carry);
+}
+
+
+template<class ApInt>
+void multiplier<ApInt, false>::sqr(ApInt& z, const ApInt& x)
+{
+ if (x.size() < ApInt::traits_type::karatsuba_sqr_threshold)
+ comba_sqr(z, x);
+ else if (x.size() < ApInt::traits_type::toom_sqr_threshold)
+ karatsuba_sqr(z, x);
+ else
+ toom3_sqr(z, x);
+}
+
+template<class ApInt>
+void multiplier<ApInt, false>::sqr(ApInt& z)
+{
+ //TODO resurrect optimization here from mp_math_v04
+ // if (z.size() < 16)
+ // comba_sqr to digit array on stack then memcpy over to z;
+ // else
+ // ApInt tmp;
+ // sqr(tmp, z);
+ ApInt tmp;
+ sqr(tmp, z);
+ z.swap(tmp);
+}
+
+template<class ApInt>
+inline
+void multiplier<ApInt, false>::comba_sqr(ApInt& z, const ApInt& x)
+{
+ z.reserve(x.size() + x.size());
+ base_multiplier_type::comba_sqr(z, x);
+}
+
+// Karatsuba squaring, computes b = a*a using three half size squarings
 //
-// 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)
+// See comments of karatsuba_mul for details. It is essentially the same
+// algorithm but merely tuned to perform recursive squarings.
 //
-// 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)
+// 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 ApInt>
+void multiplier<ApInt, false>::karatsuba_sqr(ApInt& z, const ApInt& x)
 {
- mp_int x0, x1, y0, y1, /*tmp,*/ x0y0, x1y1;
+ typedef typename ApInt::digit_type digit_type;
 
- // min # of digits
- const size_type B = std::min(size_, b.size_) / 2;
+ ApInt x0, x1, tmp, tmp2, x0x0, x1x1;
 
- // allocate memory
- x0.grow_capacity(B);
- x1.grow_capacity(size_ + b.size_);
- y0.grow_capacity(B);
- y1.grow_capacity(b.size_ - B + 1);
-
- // set size_ count
- x0.size_ = y0.size_ = B;
- x1.size_ = size_ - B;
- y1.size_ = b.size_ - B;
+ const typename ApInt::size_type B = x.size() / 2;
 
- // 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 * ( size_ - B));
- std::memcpy(y1.digits_, b.digits_ + B, s * (b.size_ - B));
+ x0.reserve(B);
+ x1.reserve(x.size() - B);
+
+ x0x0.reserve(B * 2);
+ x1x1.reserve((x.size() - B) * 2);
+
+ // now shift the digits
+ std::memcpy(x0.digits(), x.digits(), B * sizeof(digit_type));
+ std::memcpy(x1.digits(), x.digits() + B, (x.size() - B) * sizeof(digit_type));
+
+ x0.set_size(B);
+ x1.set_size(x.size() - B);
+
+ x0.clamp();
+
+ sqr(x0x0, x0);
+ sqr(x1x1, x1);
+
+ tmp = x1x1;
+ tmp += x0x0;
+
+ tmp2 = x1;
+ tmp2 -= x0;
+ sqr(tmp2);
+
+ base_adder_type::subtract_smaller_magnitude(tmp, tmp2);
+
+ if (x1x1 != digit_type(0))
+ shifter_type::shift_digits_left(x1x1, B * 2);
+ if (tmp != digit_type(0))
+ shifter_type::shift_digits_left(tmp, B);
+
+ x1x1 += tmp;
+ x1x1 += x0x0;
+
+ z.swap(x1x1);
+}
+
+// squaring using Toom-Cook 3-way algorithm
+template<class ApInt>
+void multiplier<ApInt, false>::toom3_sqr(ApInt& z, const ApInt& x)
+{
+ ApInt w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+
+ const typename ApInt::size_type B = x.size() / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ a0 = x;
+ base_divider_type::modulo_pow2(a0, traits_type::radix_bits * B);
+
+ a1 = x;
+ shifter_type::shift_digits_right(a1, B);
+ base_divider_type::modulo_pow2(a1, traits_type::radix_bits * B);
+
+ a2 = x;
+ shifter_type::shift_digits_right(a2, B * 2);
+
+ /* w0 = a0*a0 */
+ w0 = a0;
+ sqr(w0);
+
+ /* w4 = a2 * a2 */
+ w4 = a2;
+ sqr(w4);
+
+ /* w1 = (a2 + 2(a1 + 2a0))**2 */
+ w1 = a0;
+ multiply_by_2(w1);
+ w1 += a1;
+ multiply_by_2(w1);
+ w1 += a2;
+ sqr(w1);
+
+ /* w3 = (a0 + 2(a1 + 2a2))**2 */
+ w3 = a2;
+ multiply_by_2(w3);
+ w3 += a1;
+ multiply_by_2(w3);
+ w3 += a0;
+ sqr(w3);
+
+ /* w2 = (a2 + a1 + a0)**2 */
+ w2 = a1 + a2;
+ w2 += a0;
+ sqr(w2);
+
+ /* 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 */
+ base_divider_type::divide_by_2(w1);
+ /* r3/2 */
+ base_divider_type::divide_by_2(w3);
+ /* 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 *= digit_type(3);
+ w2 -= w1;
+ w2 -= w3;
+ /* r1 - r2 */
+ w1 -= w2;
+ /* r3 - r2 */
+ w3 -= w2;
+ /* r1/3 */
+ base_divider_type::divide_by_3(w1);
+ /* r3/3 */
+ base_divider_type::divide_by_3(w3);
+ /* at this point shift W[n] by B*n */
+ if (w1 != digit_type(0))
+ shifter_type::shift_digits_left(w1, 1 * B);
+ if (w2 != digit_type(0))
+ shifter_type::shift_digits_left(w2, 2 * B);
+ if (w3 != digit_type(0))
+ shifter_type::shift_digits_left(w3, 3 * B);
+ if (w4 != digit_type(0))
+ shifter_type::shift_digits_left(w4, 4 * B);
+
+ z = w0 + w1;
+ tmp1 = w2 + w3;
+ tmp1 += w4;
+ z += tmp1;
+}
+
+/*template<typename D, typename W, typename S>
+void karatsuba_mul(mp_int_base<D,W,S>& z,
+ const mp_int_base<D,W,S>& x,
+ const mp_int_base<D,W,S>& y)
+{
+ typedef D digit_type;
+ typedef S size_type;
+
+ // B is the point at which we split both numbers
+ const size_type B = std::min(x.size(), y.size()) / 2;
+
+ mp_int_base_type x0(x.digits(), B, B);
+ mp_int_base_type y0(y.digits(), B, B);
+ mp_int_base_type x1(x.digits() + B, x.size() - B, x.size() - B);
+ mp_int_base_type y1(y.digits() + B, y.size() - B, y.size() - 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;
+ mp_int_base x0y0(memory, B + 1);
+ multiply(x0y0, x0, y0);
 
- // tmp -= (x0y0 + x1y1);
- x1.sub_smaller_magnitude(x0y0);
- x1.sub_smaller_magnitude(x1y1);
+ mp_int_base x1y1(memory, B*2 + B + 1);
+ multiply(x1y1, x1, y1);
+
+ // c = (x1 + x0) * (y1 + y0)
+ add_magnitude(a, x1, x0);
+ add_magnitude(b, y1, y0);
+ multiply(c, a, b);
+
+ // c -= (x0y0 + x1y1);
+ sub_smaller_magnitude(c, x0y0);
+ sub_smaller_magnitude(c, x1y1);
 
   // shift by B
- x1.shift_digits_left(B);
- x1y1.shift_digits_left(B * 2);
+ shift_digits_left(x1, B);
+ shift_digits_left(x1y1, B * 2);
 
- x1.add_magnitude(x0y0);
- x1.add_magnitude(x1y1);
- swap(x1);
-}
+ x1y1.add_magnitude(x1y1, x1);
+ x1y1.add_magnitude(x1y1, x0y0);
+ z.swap(x1y1);
 
+ //////////////////////////////////////////////////////////
 
-// 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.size_ = digs;
+ size_type smallest_B = B;
+ while (smallest_B > karatsuba_mul_cutoff)
+ smallest_B /= 2;
 
- // compute the digits of the product directly
- for (size_type i = 0; i < size_; ++i)
+ for (size_type i = 0; i < std::min(x.size(), y.size()); i += smallest_B)
   {
- digit_type carry = 0;
+ mp_int_base_type x0(x.digits() + B*i, B, B);
+ mp_int_base_type y0(y.digits() + B*i, B, B);
+ mp_int_base_type x1(x.digits() + B, x.size() - B, x.size() - B);
+ mp_int_base_type y1(y.digits() + B, y.size() - B, y.size() - B);
 
- // limit ourselves to making digs digits of output
- const size_type pb = std::min(b.size_, 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[i+j])
- + static_cast<word_type>(digits_[i])
- * static_cast<word_type>(b[j])
- + static_cast<word_type>(carry);
 
- // the new column is the lower part of the result
- tmp[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[i+pb] = carry;
+template<class ApInt>
+struct multiplier<ApInt, true>
+{
+ typedef ApInt int_type;
+ typedef typename int_type::traits_type traits_type;
+ typedef typename traits_type::ops_type ops_type;
+ typedef typename int_type::digit_type digit_type;
+ typedef typename int_type::size_type size_type;
+
+ static void multiply_or_square(ApInt& z, const ApInt& x);
+ static void multiply_or_square(ApInt& z, const ApInt& x, const ApInt& y);
+
+ static void mul(ApInt& z, const ApInt& x, const ApInt& y);
+
+ static void multiply_by_2(ApInt& z)
+ {
+ multiplier<ApInt, false>::multiply_by_2(z);
+ }
+
+ static void sqr(ApInt& z)
+ {
+ multiplier<ApInt, false>::sqr(z);
+ z.set_sign_bit(0);
   }
 
- tmp.clamp();
+ static void sqr(ApInt& z, const ApInt& x)
+ {
+ multiplier<ApInt, false>::sqr(z, x);
+ z.set_sign_bit(0);
+ }
+};
 
- if (!tmp)
- tmp.set_sign(1);
 
- swap(tmp);
+template<class ApInt>
+void multiplier<ApInt, true>::multiply_or_square(ApInt& z, const ApInt& x)
+{
+ if (&z == &x)
+ sqr(z);
+ else
+ mul(z, z, x);
 }
 
-// FIXME no routine seems to use this
-//
-// multiplies |a| * |b| and does not compute the lower num 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 num)
-{
- mp_int tmp;
- tmp.grow_capacity(size_ + b.size_ + 1);
- tmp.size_ = size_ + b.size_ + 1;
- std::memset(tmp.digits_, 0, sizeof(digit_type) * tmp.size_);
-
- for (size_type i = 0; i < size_; ++i)
- {
- iterator dst = tmp.begin() + num;
- const_iterator z = b.begin() + (num - i);
- digit_type carry = 0;
-
- for (size_type j = num - i; j < b.size_; ++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);
+template<class ApInt>
+void
+multiplier<ApInt, true>::
+multiply_or_square(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ if (&x == &y)
+ sqr(z, x);
+ else
+ mul(z, x, y);
+}
 
- // get the lower part
- *dst++ = static_cast<digit_type>(r);
+template<class ApInt>
+void multiplier<ApInt, true>::mul(ApInt& z, const ApInt& x, const ApInt& y)
+{
+ // always multiply larger by smaller number
+ const ApInt* a = &x;
+ const ApInt* b = &y;
+ if (a->size() < b->size())
+ std::swap(a, b);
 
- // update carry
- carry = static_cast<digit_type>(r >> valid_bits);
+ if (b->size() == 1U)
+ {
+ if ((*b)[0] == 0U)
+ {
+ z.reserve(1);
+ z[0] = 0;
+ z.set_size(1);
+ z.set_sign_bit(0);
     }
- *dst = carry;
+ else if ((*b)[0] == 1U)
+ z = *a;
+ else
+ ApInt::template integral_ops<digit_type>::multiply(z, *a, (*b)[0]);
   }
+ else
+ {
+ const bool s = x.sign_bit() ^ y.sign_bit();
 
- tmp.clamp();
-
- if (!tmp)
- tmp.set_sign(1);
+ if (b->size() < traits_type::karatsuba_mul_threshold)
+ multiplier<ApInt, false>::comba_mul(z, *a, *b);
+ else if (b->size() < traits_type::toom_mul_threshold)
+ multiplier<ApInt, false>::karatsuba_mul(z, *a, *b);
+ else
+ multiplier<ApInt, false>::toom3_mul(z, *a, *b);
 
- swap(tmp);
+ z.set_sign_bit(s);
+ }
 }
 
 
-// this is a modified version of fast_s_mul_digs that only produces
-// output digits *above* num. 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 num)
-{
- mul_high_digits(b, num);
-}
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
 

Copied: sandbox/mp_math/boost/mp_math/integer/detail/power.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/pow.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/pow.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/power.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,66 +1,144 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Tom St Denis 2002 - 2007.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-// 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)
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_POWER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_POWER_HPP
+
+#include <boost/mp_math/integer/detail/multiplier.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+template<
+ class ApInt,
+ bool IsSigned = ApInt::is_signed
+>
+struct power;
+
+
+template<class ApInt>
+struct power<ApInt, false>
 {
- grow_capacity(b / digit_bits + 1);
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::size_type size_type;
 
- // set size_ to where the bit will go
- size_ = b / digit_bits + 1;
+ static void pow(ApInt& z, const ApInt& x, size_type y);
+ static void pow(ApInt& z, const ApInt& x, const ApInt& y);
+ static void pow2(ApInt& z, size_type n);
+};
 
- // set all bits to zero
- std::memset(digits_, 0, size_ * sizeof(digit_type));
-
- // put the single bit in its place
- digits_[b / digit_bits] = digit_type(1) << (b % digit_bits);
-}
 
-// calculate c = x**y using a square-multiply algorithm
-template<class A, class T>
-mp_int<A,T> pow(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type y)
+template<class ApInt>
+void power<ApInt, false>::pow(ApInt& z, const ApInt& x, size_type y)
 {
- mp_int<A,T> result;
+ z = digit_type(1);
 
- result = typename mp_int<A,T>::digit_type(1);
+ if (y == 0U)
+ return;
 
- const typename mp_int<A,T>::digit_type mask = 1 << (mp_int<A,T>::digit_bits - 1);
-
- for (int i = 0; i < mp_int<A,T>::digit_bits; ++i)
+ size_type mask = size_type(1) << (std::numeric_limits<size_type>::digits - 1);
+
+ int i = 0;
+ while (!(y & mask)) // skip leading zero bits
   {
- result.sqr();
+ ++i;
+ mask >>= 1;
+ }
+
+ for (; i < std::numeric_limits<size_type>::digits; ++i)
+ {
+ multiplier<ApInt>::sqr(z);
 
     // if the bit is set multiply
     if (y & mask)
- result *= x;
+ multiplier<ApInt>::mul(z, z, x);
 
     // shift to next bit
- y <<= 1;
+ mask >>= 1;
   }
-
- return result;
 }
 
-template<class A, class T>
-mp_int<A,T> pow(const mp_int<A,T>& x, const mp_int<A,T>& y)
+// calculate z = x^y using a square-multiply algorithm
+template<class ApInt>
+void power<ApInt, false>::pow(ApInt& z, const ApInt& x, const ApInt& y)
 {
   if (y.size() == 1)
- return pow(x, y[0]);
+ {
+ pow(z, x, y[0]);
+ return;
+ }
+
+ z = digit_type(1);
 
- mp_int<A,T> y0(y);
-
- y0.divide_by_2();
-
- mp_int<A,T> y1(y0);
+ ApInt mask(digit_type(1));
+ mask <<= y.precision() - 1; // TODO use pow2
 
- if (y.is_odd())
- ++y1;
+ for (size_type i = 0; i < y.precision(); ++i)
+ {
+ multiplier<ApInt>::sqr(z);
 
- return pow(x, y0) * pow(x, y1);
+ // if the bit is set multiply
+ if (y & mask)
+ multiplier<ApInt>::mul(z, z, x);
+
+ // shift to next bit
+ mask >>= 1;
+ }
 }
 
+// computes z = 2^n
+template<class ApInt>
+void power<ApInt, false>::pow2(ApInt& z, size_type n)
+{
+ static const size_type db = ApInt::traits_type::digit_bits;
+ const size_type q = n / db + 1;
+ const size_type r = n % db;
+
+ z.reserve(q);
+
+ std::memset(z.digits(), 0, q * sizeof(digit_type));
+
+ z[q-1] = digit_type(1) << r;
+
+ z.set_size(q);
+}
+
+
+
+template<class ApInt>
+struct power<ApInt, true>
+{
+ typedef typename ApInt::size_type size_type;
+
+ static void pow(ApInt& z, const ApInt& x, size_type y)
+ {
+ power<ApInt, false>::pow(z, x, y);
+ z.set_sign_bit(y & 1 ? x.sign_bit() : 0);
+ }
+
+ static void pow(ApInt& z, const ApInt& x, const ApInt& y)
+ {
+ if (y.is_negative())
+ throw std::domain_error("pow: negative exponent");
+ power<ApInt, false>::pow(z, x, y);
+ z.set_sign_bit(y.is_odd() ? x.sign_bit() : 0);
+ }
+
+ static void pow2(ApInt& z, size_type n)
+ {
+ power<ApInt, false>::pow2(z, n);
+ }
+};
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Modified: sandbox/mp_math/boost/mp_math/integer/detail/prime_tab.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/prime_tab.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/prime_tab.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,10 +1,10 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_DETAIL_PRIME_TAB_HPP
-#define BOOST_MP_MATH_DETAIL_PRIME_TAB_HPP
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_PRIME_TAB_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_PRIME_TAB_HPP
 
 
 namespace boost {

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/primitive_ops.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,707 +0,0 @@
-// 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 y to the digits in x and store result in z
- // xlen must be > 0
- // returns: the last carry (it will not get stored in z)
- static digit_type add_single_digit(digit_type* z,
- const digit_type* x, size_type xlen,
- digit_type y);
-
- // 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
- // returns last carry
- static digit_type add_smaller_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* x, size_type xlen,
- digit_type y);
-
- // 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* x, size_type xlen,
- digit_type y);
-
- // z = x * 2
- static digit_type multiply_by_two(digit_type* z,
- const digit_type* x, size_type len);
-
- // z = x * y
- static void classic_mul(digit_type* z, const digit_type* x, size_type xlen,
- const digit_type* y, size_type ylen);
-
- // z = x * y; precondition: xlen >= ylen
- static void comba_mul(digit_type* z, const digit_type* x, size_type xlen,
- const digit_type* y, size_type ylen);
-
- // 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 xylen);
-
- // SQR ------------------------------------
-
- // z = x * x;
- static void comba_sqr(digit_type* z, const digit_type* x, size_type xlen);
-
- // MADD ------------------------------------
-
- // z = w * x + y
- static digit_type multiply_add_digits(digit_type* z,
- const digit_type* w,
- digit_type x,
- const digit_type* y,
- size_type n);
-
- // DIV -------------------------------------
-
- // z = x / 2
- static void divide_by_two(digit_type* z, const digit_type* x, size_type len);
-
- // z = x / y
- // returns remainder
- static digit_type divide_by_digit(digit_type* z,
- const digit_type* x, size_type xlen,
- digit_type y);
-};
-
-
-
-template<typename D, typename W, typename S>
-inline
-D basic_primitive_ops<D,W,S>::add_single_digit(digit_type* z,
- const digit_type* x,
- size_type xlen,
- digit_type y)
-{
- word_type carry = static_cast<word_type>(*x++) + y;
- *z++ = static_cast<digit_type>(carry);
- carry >>= digit_bits;
-
- while (carry && --xlen)
- {
- carry += static_cast<word_type>(*x++);
- *z++ = static_cast<digit_type>(carry);
- carry >>= digit_bits;
- }
-
- return static_cast<digit_type>(carry);
-}
-
-
-template<typename D, typename W, typename S>
-inline
-D basic_primitive_ops<D,W,S>::add_digits(digit_type* z,
- const digit_type* x,
- const digit_type* y, size_type n)
-{
- word_type carry = 0;
-
- 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
-S basic_primitive_ops<D,W,S>::ripple_carry(digit_type* z,
- const digit_type* x,
- size_type n,
- digit_type& carry)
-{
- word_type c = carry;
- size_type i = 0;
-
- 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
-D basic_primitive_ops<D,W,S>::add_smaller_magnitude(digit_type* z,
- const digit_type* x,
- size_type xlen,
- const digit_type* y,
- size_type ylen)
-{
- digit_type carry = add_digits(z, x, y, ylen);
-
- size_type n = ripple_carry(z + ylen, x + ylen, xlen - ylen, carry);
-
- n += ylen;
-
- if (n < xlen && z != x)
- std::memcpy(z + n, x + n, sizeof(digit_type) * (xlen - n));
-
- return carry;
-}
-
-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
-D basic_primitive_ops<D,W,S>::subtract_digits(digit_type* z,
- const digit_type* x,
- const digit_type* y,
- size_type n)
-{
- word_type borrow = 0;
-
- 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
-S basic_primitive_ops<D,W,S>::ripple_borrow(digit_type* z,
- const digit_type* x,
- size_type n,
- digit_type borrow)
-{
- word_type b = borrow;
- size_type i = 0;
- 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);
-
- size_type n = ripple_borrow(z + ylen, x + ylen, xlen - ylen, borrow);
-
- if (z != x)
- {
- n += ylen;
- std::memcpy(z + n, x + n, (xlen - n) * sizeof(digit_type));
- }
-}
-
-template<typename D, typename W, typename S>
-inline
-D basic_primitive_ops<D,W,S>::multiply_by_digit(digit_type* z,
- const digit_type* y,
- size_type ylen,
- digit_type x)
-{
- digit_type carry = 0;
-
- 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>
-inline
-D basic_primitive_ops<D,W,S>::multiply_by_two(digit_type* z,
- const digit_type* x, size_type n)
-{
- static const digit_type one = 1U;
-
- digit_type carry = 0;
-
- while (n--)
- {
- // get carry bit for next iteration
- const digit_type r = *x >> (static_cast<digit_type>(digit_bits) - one);
-
- *z++ = (*x++ << one) | carry;
-
- carry = r;
- }
-
- return carry;
-}
-
-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 xlen,
- const digit_type* y, size_type ylen)
-{
- // phase 1
- word_type tmp = static_cast<word_type>(x[0]) * static_cast<word_type>(y[0]);
- z[0] = static_cast<digit_type>(tmp);
-
- for (size_type i = 1; i < xlen; ++i)
- {
- tmp = (tmp >> digit_bits)
- + static_cast<word_type>(x[i])
- * static_cast<word_type>(y[0]);
- z[i] = static_cast<digit_type>(tmp);
- }
-
- tmp >>= digit_bits;
- z[xlen] = static_cast<digit_type>(tmp);
-
- // phase 2
- for (size_type i = 1; i < ylen; ++i)
- {
- 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 < xlen; ++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 + xlen] = 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 xlen,
- const digit_type* y, size_type ylen)
-{
- assert(xlen >= ylen);
-
- word_type acc = 0; // accumulator for each column
- word_type carry = 0;
-
- // phase 1
- for (size_type i = 0; i < ylen; ++i)
- {
- const digit_type* a = x;
- const digit_type* b = y + i;
-
- for (size_type j = 0; j <= i; ++j)
- {
- acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
- 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 < xlen - ylen; ++i)
- {
- const digit_type* a = x + ylen + i;
- const digit_type* b = y;
-
- for (size_type j = 0; j < ylen; ++j)
- {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
- 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 3
- for (size_type i = 0; i < ylen - 1; ++i)
- {
- const digit_type* a = x + xlen - 1;
- const digit_type* b = y + i + 1;
-
- for (size_type j = i + 1; j < ylen; ++j)
- {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
- 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 xylen)
-{
- word_type acc = 0; // accumulator for each column
- word_type carry = 0;
-
- // phase 1
- for (size_type i = 0; i < xylen; ++i)
- {
- const digit_type* a = x;
- const digit_type* b = y + i;
-
- for (size_type j = 0; j <= i; ++j)
- {
- acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
- 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 = 1; i < xylen; ++i)
- {
- const digit_type* a = y + xylen - 1;
- const digit_type* b = x + i;
-
- for (size_type j = 0; j < xylen - i; ++j)
- {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
- 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 xlen)
-{
-/* word_type acc = 0;
- word_type carry = 0;
- word_type acc2;
-
- for (size_type i = 0; i < xlen; ++i)
- {
- // even colum
- acc += static_cast<word_type>(x[i]) * static_cast<word_type>(x[i]);
-
- const digit_type* a = x + i;
- const digit_type* b = x + i;
-
- acc2 = 0;
- for (size_type j = 0; j < (i - n&1) >> 1; ++j)
- {
- acc2 += static_cast<word_type>(*(--a)) * static_cast<word_type>(*(--b));
- carry += acc2 >> digit_bits;
- acc2 = static_cast<digit_type>(acc2);
- }
-
- acc += acc2 + acc2;
-
- *z++ = static_cast<digit_type>(acc);
- acc = static_cast<digit_type>(carry);
- carry >>= digit_bits;
-
- // odd column
- const digit_type* a = x + i;
- const digit_type* b = x + i + 1;
-
- acc2 = 0;
- for (size_type j = 0; j <= i; ++j)
- {
- acc2 += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
- carry += acc2 >> digit_bits;
- acc2 = static_cast<digit_type>(acc2);
- }
-
- acc += acc2 + acc2;
-
- *z++ = static_cast<digit_type>(acc);
- acc = static_cast<digit_type>(carry);
- carry >>= digit_bits;
- }
-
- *z = static_cast<digit_type>(acc);*/
-
-
- word_type acc = 0; // accumulator for each column
- word_type carry = 0;
-
- // phase 1
- for (size_type i = 0; i < xlen; ++i)
- {
- const digit_type* a = x;
- const digit_type* b = x + i;
-
- for (size_type j = 0; j <= i; ++j)
- {
- acc += static_cast<word_type>(*a++) * static_cast<word_type>(*b--);
- 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 = 1; i < xlen; ++i)
- {
- const digit_type* a = x + xlen - 1;
- const digit_type* b = x + i;
-
- for (size_type j = 0; j < xlen - i; ++j)
- {
- acc += static_cast<word_type>(*a--) * static_cast<word_type>(*b++);
- 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>
-D basic_primitive_ops<D,W,S>::multiply_add_digits(digit_type* z,
- const digit_type* w,
- digit_type x,
- const digit_type* y,
- size_type n)
-{
- word_type carry = 0;
- while (n--)
- {
- const word_type r = static_cast<word_type>(*w++)
- * static_cast<word_type>(x)
- + static_cast<word_type>(*y++)
- + carry;
-
- *z++ = static_cast<digit_type>(r);
- carry = r >> digit_bits;
- }
-
- return static_cast<digit_type>(carry);
-}
-
-
-template<typename D, typename W, typename S>
-inline
-void basic_primitive_ops<D,W,S>::divide_by_two(digit_type* z,
- const digit_type* x, size_type n)
-{
- z += n - 1;
- x += n - 1;
-
- digit_type carry = 0;
-
- while (n--)
- {
- // get carry for next iteration
- const digit_type r = *x & 1;
-
- *z-- = (*x-- >> 1) | (carry << (digit_bits - 1));
-
- carry = r;
- }
-}
-
-template<typename D, typename W, typename S>
-D basic_primitive_ops<D,W,S>::divide_by_digit(digit_type* z,
- const digit_type* x, size_type n,
- digit_type y)
-{
- z += n - 1;
- x += n - 1;
-
- word_type w = 0;
-
- while (n--)
- {
- w = (w << digit_bits) | static_cast<word_type>(*x--);
- digit_type tmp;
- if (w >= y)
- {
- tmp = static_cast<digit_type>(w / y);
- w -= tmp * y;
- }
- else
- tmp = 0;
- *z-- = tmp;
- }
-
- return static_cast<digit_type>(w);
-}
-
-
-
-
-// This exists to ease development of primitive_ops specializations. If a
-// 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
-

Copied: sandbox/mp_math/boost/mp_math/integer/detail/root.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/root.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/root.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/root.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,202 +1,225 @@
+// Copyright Tom St Denis 2002 - 2007.
 // Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_ROOT_HPP
-#define BOOST_MP_MATH_MP_INT_ROOT_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_ROOT_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_ROOT_HPP
 
+#include <boost/mp_math/integer/detail/multiplier.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
 
 namespace boost {
 namespace mp_math {
+namespace detail {
 
-template<class A, class T>
-mp_int<A,T> sqrt(const mp_int<A,T>& x)
+// Newton-Raphson approximation
+template<class ApInt, typename IntegerT>
+void
+newton_raphson_loop(ApInt& a, ApInt& b, const IntegerT& n, const ApInt& x)
 {
- if (x.is_negative())
- throw std::domain_error("sqrt: argument must be positive");
-
- mp_int<A,T> t1;
-
- if (!x)
- {
- t1.zero();
- return t1;
- }
-
- t1 = x;
-
- // First approx. (not very bad for large arg)
- t1.shift_digits_right(t1.size()/2);
+ //std::cout << "initial = " << b.template to_string<std::string>(std::ios::hex) << std::endl;
+ // a is going to hold the result
+ // b holds the initial approximation
+ // c is just another temporary
+ ApInt c;
 
- // t1 > 0
- mp_int<A,T> t2 = x / t1;
-
- t1 += t2;
- t1.divide_by_2();
- // And now t1 > sqrt(arg)
+ // improve the initial approximation b
   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;
-}
+ a = b;
 
+ // b = a - (a^n - x) / (n * a^(n-1))
 
-// Uses Newton-Raphson approximation.
-template<class A, class T>
-mp_int<A,T> nth_root(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n)
-{
- if ((n & 1) == 0 && x.is_negative())
- throw std::domain_error("nth_root: argument must be positive if n is even");
-
- if (n == 0U)
- throw std::domain_error("nth_root: n must not be zero");
- else if (n == 1U)
- return x;
-
- // if x is negative fudge the sign but keep track
- const int neg = x.sign();
- const_cast<mp_int<A,T>*>(&x)->set_sign(1);
-
- mp_int<A,T> t1, t2, t3;
-
- typedef typename mp_int<A,T>::size_type size_type;
-
- // initial approximation
- const size_type result_precision = (x.precision() - 1) / n + 1;
- t2.grow_capacity(1);
- t2.set_size(1);
- t2[0] = 0;
- t2.set_bits(0, result_precision + 1);
-
- do
- {
- t1 = t2;
-
- // t2 = t1 - ((t1**n - x) / (n * t1**(n-1)))
-
- // t3 = t1**(n-1)
- t3 = pow(t1, n-1);
+ c = pow(a, n-1);
 
+ //std::cout << "c = " << c.template to_string<std::string>(std::ios::hex) << std::endl;
+ //std::cout << "a = " << a.template to_string<std::string>(std::ios::hex) << std::endl;
+ //std::cout << "x = " << x.template to_string<std::string>(std::ios::hex) << std::endl;
     // numerator
- // t2 = t1**n
- t2 = t3 * t1;
-
- // t2 = t1**n - x
- t2 -= x;
+ b = c * a; // b = a^n
+ //std::cout << "b = " << b.template to_string<std::string>(std::ios::hex) << std::endl;
+ b -= x; // b = a^n - x
+ //std::cout << "b = " << b.template to_string<std::string>(std::ios::hex) << std::endl;
 
     // denominator
- // t3 = t1**(n-1) * n
- t3.multiply_by_digit(n);
+ c *= n; // c = a^(n-1) * n
+ c = b / c; // c = (a^n - x) / (n * a^(n-1))
 
- // t3 = (t1**n - x)/(n * t1**(n-1))
- t3 = t2 / t3;
-
- t2 = t1 - t3;
- } while (t1 != t2);
+ //std::cout << "c = " << c.template to_string<std::string>(std::ios::hex) << std::endl;
+ //std::cout << " ok " << std::endl;
+ b = a - c;
+ //std::cout << " ok2 " << std::endl;
+ } while (a != b);
 
   // result can be off by a few so check
   for (;;)
   {
- t2 = pow(t1, n);
+ b = pow(a, n);
 
- if (t2 > x)
- --t1;
+ if (b > x)
+ --a;
     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);
+template<
+ class ApInt,
+ bool IsApIntSigned = ApInt::is_signed
+>
+struct root;
 
- return t1;
-}
 
-template<class A, class T>
-mp_int<A,T> nth_root(const mp_int<A,T>& x, const mp_int<A,T>& n)
+template<class ApInt>
+struct root<ApInt,false>
 {
- if (n.is_odd() && x.is_negative())
- throw std::domain_error("nth_root: argument must be positive if n is even");
-
- if (n.size() == 1)
- return nth_root(x, n[0]);
+ typedef typename ApInt::size_type size_type;
 
- // 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);
+ static void sqrt (ApInt& z, const ApInt& x);
+ template<typename IntegerT>
+ static void nth_root(ApInt& z, const IntegerT& n, const ApInt& x);
+};
 
- mp_int<A,T> t1, t2, t3;
 
- typedef typename mp_int<A,T>::size_type size_type;
+template<class ApInt>
+void
+root<ApInt,false>::sqrt(ApInt& z, const ApInt& x)
+{
+ if (!x)
+ {
+ z = typename ApInt::digit_type(0);
+ return;
+ }
 
- static const size_type digit_bits = mp_int<A,T>::digit_bits;
+ z = x;
 
- const size_type result_precision = (x.precision() - 1)
- / n.template to_integral<size_type>() + 1;
+ // first approx. (not very bad for large arg)
+ shifter<ApInt>::shift_digits_right(z, z.size() / 2);
 
- t2.grow_capacity((result_precision + digit_bits - 1) / digit_bits);
- t2.set_size ((result_precision + digit_bits - 1) / digit_bits);
+ ApInt a = x / z;
 
- t2[t2.size()-1] = 0;
- t2.set_bits(0, result_precision + 1);
+ z += a;
+ base::divider<ApInt>::divide_by_2(z);
 
+ // and now z > sqrt(x)
   do
   {
- t1 = t2;
+ a = x / z;
+ z += a;
+ base::divider<ApInt>::divide_by_2(z);
+ // z >= sqrt(x) >= a at this point
+ } while (z > a);
+}
+
+template<class ApInt>
+template<typename IntegerT>
+void
+root<ApInt,false>::nth_root(ApInt& z, const IntegerT& n, const ApInt& x)
+{
+ if (n == 0U)
+ throw std::domain_error("nth_root: n must not be zero");
+ else if (n == 1U)
+ {
+ z = x;
+ return;
+ }
 
- // t2 = t1 - ((t1**n - x) / (n * t1**(n-1)))
+ static const size_type digit_bits = ApInt::traits_type::digit_bits;
 
- // t3 = t1**(n-1)
- t3 = pow(t1, n-1);
+ // create initial approximation
+ z = x.precision() - 1;
+ z /= n;
+ const size_type result_precision = z.template to_integral<size_type>() + 1;
+
+ const size_type result_digits = (result_precision + (digit_bits - 1))
+ / digit_bits;
+ ApInt initial_approximation;
+ initial_approximation.reserve (result_digits);
+ initial_approximation.set_size(result_digits);
 
- // numerator
- // t2 = t1**n
- t2 = t3 * t1;
+ initial_approximation[result_digits - 1] = 0;
+ initial_approximation.set_bits(0, result_precision + 1);
 
- // t2 = t1**n - x
- t2 -= x;
+ newton_raphson_loop(z, initial_approximation, n, x);
+}
 
- // denominator
- // t3 = t1**(n-1) * n
- t3 *= n;
 
- // t3 = (t1**n - x)/(n * t1**(n-1))
- t3 = t2 / t3;
+template<class ApInt>
+struct root<ApInt,true>
+{
+ typedef typename ApInt::size_type size_type;
 
- t2 = t1 - t3;
- } while (t1 != t2);
+ static void sqrt (ApInt& z, const ApInt& x);
+ static void nth_root(ApInt& z, size_type n, const ApInt& x);
+ static void nth_root(ApInt& z, const ApInt& n, const ApInt& x);
+};
 
- // result can be off by a few so check
- for (;;)
- {
- t2 = pow(t1, n);
 
- if (t2 > x)
- --t1;
- else
- break;
+template<class ApInt>
+void
+root<ApInt,true>::sqrt(ApInt& z, const ApInt& x)
+{
+ if (x.is_negative())
+ throw std::domain_error("sqrt: radicand must be positive");
+
+ root<ApInt,false>::sqrt(z, x);
+}
+
+template<class ApInt>
+void
+root<ApInt,true>::nth_root(ApInt& z, size_type n, const ApInt& x)
+{
+ if ((n & 1) == 0 && x.is_negative())
+ throw std::domain_error("nth_root: radicand must be positive if n is even");
+
+ // x must be positive for the algorithm to work
+ const bool s = x.sign_bit();
+ const_cast<ApInt&>(x).set_sign_bit(0);
+
+ try
+ {
+ root<ApInt,false>::nth_root(z, n, x);
+ }
+ catch (const std::exception&)
+ {
+ const_cast<ApInt&>(x).set_sign_bit(s);
+ throw;
   }
 
- // reset the sign of x first
- const_cast<mp_int<A,T>*>(&x)->set_sign(neg);
+ const_cast<ApInt&>(x).set_sign_bit(s);
+ z.set_sign_bit(s);
+}
+
+template<class ApInt>
+void
+root<ApInt,true>::nth_root(ApInt& z, const ApInt& n, const ApInt& x)
+{
+ if (n.is_even() && x.is_negative())
+ throw std::domain_error("nth_root: radicand must be positive if n is even");
+
+ // x must be positive for the algorithm to work
+ const bool s = x.sign_bit();
+ const_cast<ApInt&>(x).set_sign_bit(0);
 
- // set the sign of the result
- t1.set_sign(neg);
+ try
+ {
+ root<ApInt,false>::nth_root(z, n, x);
+ }
+ catch (const std::exception&)
+ {
+ const_cast<ApInt&>(x).set_sign_bit(s);
+ throw;
+ }
 
- return t1;
+ const_cast<ApInt&>(x).set_sign_bit(s);
+ z.set_sign_bit(s);
 }
 
 
+} // namespace detail
 } // namespace mp_math
 } // namespace boost
 

Copied: sandbox/mp_math/boost/mp_math/integer/detail/string_conversion.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/detail/string_conversion.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,314 +1,985 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-namespace detail
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_STRING_CONVERTER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_STRING_CONVERTER_HPP
+
+#include <algorithm>
+#include <iostream>
+#include <memory>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+template<
+ typename T,
+ T Radix,
+ T Count = 0,
+ T Temp = Radix,
+ bool continue_recursion = true
+>
+struct max_power_impl
 {
- template<typename charT>
- inline int ascii_to_value(const charT c)
+ // continue recursion until Temp overflows
+ static const T a = static_cast<T>(Temp * Radix);
+ static const bool c = (a / Radix) == Temp;
+
+ typedef max_power_impl<T, Radix, Count + 1, c ? a : Temp, c> result;
+
+ static const T exponent = result::exponent;
+ static const T value = result::value;
+};
+
+template<typename T, T Radix, T Count, T Temp>
+struct max_power_impl<T, Radix, Count, Temp, false>
+{
+ static const T exponent = Count;
+ static const T value = Temp;
+};
+
+// T must be an unsigned integral type
+template<typename T, T Radix>
+struct max_power
+{
+ static const T exponent = max_power_impl<T, Radix>::exponent;
+ static const T value = max_power_impl<T, Radix>::value;
+};
+
+
+// Supported radices are 2, 4, 8, 16, 32, 64 and 10
+template<class ApInt>
+struct sc_constants
+{
+ typedef typename ApInt::digit_type digit_type;
+
+//private:
+
+ const unsigned index_;
+
+ static unsigned map_radix_to_index(unsigned radix)
   {
- switch (c)
+ switch (radix) // map radix 2^x to index x-1
     {
- 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;
+ case 2: return 0;
+ case 4: return 1;
+ case 8: return 2;
+ case 16: return 3;
+ case 32: return 4;
+ case 64: return 5;
+ default: return 6; // map radix 10 to index 6
     }
- return c;
   }
+
+ static const digit_type max_exponent_array_[7];
+ static const digit_type max_power_value_array_[7];
+ static const digit_type radix_storage_bits_array_[7];
+
+public:
+
+ explicit sc_constants(unsigned radix)
+ :
+ index_(map_radix_to_index(radix))
+ {}
+
+ // returns maximal exponent x so that radix^x still fits into a digit_type
+ digit_type max_exponent() const
+ {
+ return max_exponent_array_[index_];
+ }
+
+ // returns the corresponding value y = radix^max_power
+ digit_type max_power_value() const
+ {
+ return max_power_value_array_[index_];
+ }
+
+ // returns ceil(log2(radix))
+ digit_type radix_storage_bits() const
+ {
+ return radix_storage_bits_array_[index_];
+ }
+};
+
+template<class ApInt>
+const typename ApInt::digit_type
+sc_constants<ApInt>::max_exponent_array_[7] =
+{
+ max_power<digit_type, 2>::exponent,
+ max_power<digit_type, 4>::exponent,
+ max_power<digit_type, 8>::exponent,
+ max_power<digit_type, 16>::exponent,
+ max_power<digit_type, 32>::exponent,
+ max_power<digit_type, 64>::exponent,
+ max_power<digit_type, 10>::exponent
+};
+
+template<class ApInt>
+const typename ApInt::digit_type
+sc_constants<ApInt>::max_power_value_array_[7] =
+{
+ max_power<digit_type, 2>::value,
+ max_power<digit_type, 4>::value,
+ max_power<digit_type, 8>::value,
+ max_power<digit_type, 16>::value,
+ max_power<digit_type, 32>::value,
+ max_power<digit_type, 64>::value,
+ max_power<digit_type, 10>::value
+};
+
+template<class ApInt>
+const typename ApInt::digit_type
+sc_constants<ApInt>::radix_storage_bits_array_[7] = {1, 2, 3, 4, 5, 6, 4};
+
+
+// Always call detect_properties before calling convert, unless you're providing
+// the radix explicitly. In that case the number must not have a radix prefix.
+
+template<class ApInt>
+struct from_string_converter
+{
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::size_type size_type;
+
+ // detect sign, radix, length
+ template<typename Iter>
+ void detect_properties(Iter& first, Iter last)
+ {
+ detect_properties(first, last,
+ typename std::iterator_traits<Iter>::iterator_category());
+ }
+
+ // as above, additionally it checks if the number prefix is formatted
+ // according to the flags
+ template<typename Iter>
+ void detect_properties(Iter& first, Iter last, std::ios_base::fmtflags f);
+
+ // manual radix parameter for radices 2-64
+ template<typename Iter>
+ void convert(ApInt& x, Iter first, Iter last, unsigned radix) const
+ {
+ assert(x.is_uninitialized());
+ if (first != last)
+ convert(x, first, last, radix,
+ typename std::iterator_traits<Iter>::iterator_category());
+ }
+
+ // use the detected radix, can only be 8, 10 or 16
+ template<typename Iter>
+ void convert(ApInt& x, Iter first, Iter last) const
+ {
+ convert(x, first, last, radix);
+ }
+
+ template<typename InputIter>
+ void convert(ApInt& x, InputIter c) const;
+
+ // converts the string [first, last) to digits one at a time beginning with
+ // the most significant digit, works only for power of two radices
+ template<typename Iter>
+ digit_type get_next_digit(Iter& first, Iter last) const;
+
+ static bool is_power_of_two(unsigned radix)
+ {
+ return (radix & (radix - 1)) == 0;
+ }
+
+ // properties
+ std::size_t total_length;
+ unsigned prefix_length;
+ std::size_t length; // = total_length - prefix_length
+ unsigned radix;
+ bool is_positive; // do we have a '-' as first character?
+
+private:
+
+ typedef sc_constants<ApInt> sc_type;
+ typedef typename ApInt::traits_type::ops_type ops_type;
+
+ static const unsigned radix_bits = ApInt::traits_type::radix_bits;
+
+ enum error_t
+ {
+ err_invalid_char,
+ err_bad_prefix,
+ err_no_number_after_prefix,
+ err_no_number_after_sign,
+ err_no_error
+ };
+
+ template<typename charT>
+ static digit_type ascii_to_value(charT c);
+
+ template<typename RandomAccessIterator>
+ void detect_properties(RandomAccessIterator& first,
+ RandomAccessIterator last,
+ std::random_access_iterator_tag);
+
+ template<typename InputIterator>
+ void detect_properties(InputIterator& first,
+ InputIterator last,
+ std::input_iterator_tag);
+
+ template<typename RandomAccessIterator>
+ void convert(ApInt& x,
+ RandomAccessIterator first, RandomAccessIterator last,
+ unsigned radix,
+ std::random_access_iterator_tag) const;
+
+ template<typename InputIterator>
+ void convert(ApInt& x,
+ InputIterator first, InputIterator last,
+ unsigned radix,
+ std::input_iterator_tag) const;
+
+ template<typename Iter>
+ void convert_pow2_radix(
+ ApInt& x, Iter first, Iter last, unsigned radix, const sc_type& sc) const
+ {
+ convert_pow2_radix(x, first, last, radix, sc,
+ typename std::iterator_traits<Iter>::iterator_category());
+ }
+
+ template<typename Iter>
+ void convert_other_radix(ApInt& x,
+ Iter first, Iter last,
+ unsigned radix,
+ const sc_type& sc) const
+ {
+ convert_other_radix(x, first, last, radix, sc,
+ typename std::iterator_traits<Iter>::iterator_category());
+ }
+
+ template<typename RandomAccessIterator>
+ void convert_pow2_radix(ApInt& x,
+ RandomAccessIterator first, RandomAccessIterator last,
+ unsigned radix,
+ const sc_type& sc,
+ std::random_access_iterator_tag) const;
+
+ template<typename RandomAccessIterator>
+ void convert_other_radix(ApInt& x,
+ RandomAccessIterator first, RandomAccessIterator last,
+ unsigned radix,
+ const sc_type& sc,
+ std::random_access_iterator_tag) const;
+
+ template<typename InputIterator>
+ void convert_pow2_radix(ApInt& x,
+ InputIterator first, InputIterator last,
+ unsigned radix,
+ const sc_type& sc,
+ std::input_iterator_tag) const;
+
+ template<typename InputIterator>
+ void convert_other_radix(ApInt& x,
+ InputIterator first, InputIterator last,
+ unsigned radix,
+ const sc_type& sc,
+ std::input_iterator_tag) const;
+};
+
+
+template<class ApInt>
+template<typename charT>
+inline
+typename ApInt::digit_type
+from_string_converter<ApInt>::ascii_to_value(charT c)
+{
+ switch (c)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c = c - '0';
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ c = c - 'A' + 10;
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ c = c - 'a' + 10;
+ }
+ return static_cast<digit_type>(c);
 }
 
-// low level from string conversion routine
-// Requires:
-// - size_ = 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)
+
+// pre: first <= last
+template<class ApInt>
+template<typename RandomAccessIterator>
+void from_string_converter<ApInt>::
+detect_properties(RandomAccessIterator& first, RandomAccessIterator last,
+ std::random_access_iterator_tag)
 {
- assert(size_ == 0);
- assert(first != last);
+ const RandomAccessIterator beg = first;
 
- const detail::string_conversion_constants<mp_int> sc(radix);
+ detect_properties(first, last, std::input_iterator_tag());
 
- const size_type length = std::distance(first, last);
+ total_length = std::distance(beg, last);
+ prefix_length = std::distance(beg, first);
+ length = total_length - prefix_length;
+};
+
+// pre: first <= last
+template<class ApInt>
+template<typename InputIterator>
+void from_string_converter<ApInt>::
+detect_properties(InputIterator& first, InputIterator last,
+ std::input_iterator_tag)
+{
+ if (first == last)
+ {
+ is_positive = true;
+ return;
+ }
 
- 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)
+ if (*first == '-')
   {
- const size_type required =
- (length * sc.radix_storage_bits + (valid_bits - 1)) / valid_bits;
- grow_capacity(required);
+ ++first;
+ is_positive = false;
+ }
+ else
+ {
+ if (*first == '+')
+ ++first;
+ is_positive = true;
+ }
 
- 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)
+ // detect the radix
+ if (first != last)
+ {
+ if (*first == '0') // octal
+ {
+ ++first;
+ if (first != last && (*first == 'x' || *first == 'X')) // hex
       {
- push(result);
- offset -= valid_bits;
- result = static_cast<digit_type>(x >> (sc.radix_storage_bits - offset));
+ radix = 16;
+ ++first;
+ }
+ else
+ {
+ radix = 8;
+ --first; // keep the zero, necessary for int_type("0")
       }
     }
-
- if (result || is_uninitialized())
- push(result);
-
- clamp();
+ else // decimal
+ radix = 10;
+ }
+ else
+ throw std::invalid_argument(
+ "from_string_converter::detect_properties: malformed string");
+};
+
+template<class ApInt>
+template<typename Iter>
+void from_string_converter<ApInt>::
+detect_properties(Iter& first, Iter last, std::ios_base::fmtflags f)
+{
+ total_length = std::distance(first, last);
+
+ if (first == last)
+ return;
 
- if (!*this)
- set_sign(1);
+ const Iter beg = first;
+
+ if (*first == '-')
+ {
+ is_positive = false;
+ ++first;
   }
- else // radix can only be 10 at this point
+ else
   {
- size_type required;
- // approximate log2(10) with 10/3
- if (length < std::numeric_limits<size_type>::max()/10U)
- required = (10U * length + 2U) / 3U;
+ if (f & std::ios_base::showpos)
+ {
+ if (*first == '+')
+ ++first;
+ else
+ throw std::invalid_argument(
+ "from_string_converter::detect_properties: expected a '+' sign");
+ }
+ is_positive = true;
+ }
+
+ // TODO should uppercase also mean that hex prefix must be 0X?
+ //const bool uppercase = f & std::ios_base::uppercase;
+ const bool showbase = f & std::ios_base::showbase;
+
+ bool bad_prefix = false;
+
+ if (f & std::ios_base::hex)
+ {
+ if (showbase)
+ {
+ if (*first == '0')
+ ++first;
+ else
+ bad_prefix = true;
+ if (*first == 'x' || *first == 'X')
+ ++first;
+ else
+ bad_prefix = true;
+ }
+ radix = 16;
+ }
+ else if (f & std::ios_base::oct)
+ {
+ if (showbase)
+ {
+ if (*first != '0') // keep the zero, necessary for int_type("0")
+ bad_prefix = true;
+ }
+ radix = 8;
+ }
+ else if (f & std::ios_base::dec)
+ radix = 10;
+ else
+ throw std::invalid_argument(
+ "from_string_converter::detect_properties: unknown radix");
+
+ if (bad_prefix)
+ throw std::invalid_argument(
+ "from_string_converter::detect_properties: bad radix prefix");
+
+ prefix_length = std::distance(beg, first);
+ length = total_length - prefix_length;
+}
+
+template<class ApInt>
+template<typename RandomAccessIterator>
+void
+from_string_converter<ApInt>::
+convert_pow2_radix(ApInt& x,
+ RandomAccessIterator first, RandomAccessIterator last,
+ unsigned radix,
+ const sc_type& sc,
+ std::random_access_iterator_tag) const
+{
+ digit_type result = 0;
+ int offset = 0;
+
+ typedef std::reverse_iterator<RandomAccessIterator> reverse_iter_type;
+ for (reverse_iter_type c(last); c != reverse_iter_type(first); ++c)
+ {
+ const digit_type y = static_cast<digit_type>(ascii_to_value(*c));
+
+ if (y >= radix)
+ throw std::invalid_argument("inv_msg");
+
+ result |= y << offset;
+ offset += sc.radix_storage_bits();
+
+ if (offset >= static_cast<int>(radix_bits))
+ {
+ x.push(result);
+ offset -= radix_bits;
+ result = static_cast<digit_type>(y >> (sc.radix_storage_bits() - offset));
+ }
+ }
+
+ if (result || x.is_uninitialized())
+ x.push(result);
+
+ x.clamp();
+}
+
+template<class ApInt>
+template<typename RandomAccessIterator>
+void
+from_string_converter<ApInt>::
+convert_other_radix(ApInt& x,
+ RandomAccessIterator first, RandomAccessIterator last,
+ unsigned radix,
+ const sc_type& sc,
+ std::random_access_iterator_tag) const
+{
+ for (size_type i = sc.max_exponent(); i < length; i += sc.max_exponent())
+ {
+ digit_type result = 0U;
+
+ // first convert a block of decimal digits to radix 10^sc.max_exponent
+ // which will still fit into a digit_type
+ for (unsigned int j = 0; j < sc.max_exponent(); ++j)
+ {
+ const digit_type y = *first++ - '0';
+ if (y >= 10U)
+ throw std::invalid_argument("inv_msg");
+ result = result * 10U + y;
+ }
+
+ // then use multi precision routines to convert this digit to binary
+ if (x.is_initialized())
+ {
+ digit_type carry =
+ ops_type::multiply_by_digit(x.digits(),
+ x.digits(), x.size(),
+ sc.max_power_value());
+
+ carry += ops_type::add_single_digit(x.digits(),
+ x.digits(), x.size(),
+ result);
+
+ if (carry)
+ x.push(carry);
+ }
     else
- required = length / 3U * 10U;
- required = (required + (valid_bits - 1)) / valid_bits;
-
- grow_capacity(required);
+ x.push(result);
+ }
+
+ // one last round for the remaining decimal digits
+ if (first != last)
+ {
+ digit_type radix_power = 1U;
+ digit_type result = 0U;
 
- for (size_type i = sc.max_power; i < length; i += sc.max_power)
+ while (first != last)
     {
- digit_type result = 0U;
+ const digit_type y = *first++ - '0';
+ if (y >= 10U)
+ throw std::invalid_argument("inv_msg");
+ result = result * 10U + y;
+ radix_power *= 10U;
+ }
 
- // 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;
- }
+ if (x.size())
+ {
+ digit_type carry =
+ ops_type::multiply_by_digit(x.digits(), x.digits(), x.size(),
+ static_cast<digit_type>(radix_power));
+
+ carry += ops_type::add_single_digit(x.digits(),
+ x.digits(), x.size(),
+ result);
 
- // then use multi precision routines to convert this digit to binary
- if (size_)
- {
- digit_type carry = ops_type::multiply_by_digit(digits_, digits_, size_,
- sc.max_power_value);
+ if (carry)
+ x.push(carry);
+ }
+ else
+ x.push(result);
+ }
+}
 
- carry += ops_type::add_single_digit(digits_, digits_, size_, result);
-
- if (carry)
- push(carry);
- }
- else
- push(result);
+template<class ApInt>
+template<typename InputIterator>
+void
+from_string_converter<ApInt>::
+convert_pow2_radix(ApInt& x,
+ InputIterator first, InputIterator last,
+ unsigned radix,
+ const sc_type& sc,
+ std::input_iterator_tag) const
+{
+ digit_type result = 0;
+ int offset = 0;
+ size_type bits_read = 0;
+
+ for (; first != last; ++first)
+ {
+ const digit_type y = static_cast<digit_type>(ascii_to_value(*first));
+
+ if (y >= radix)
+ throw std::invalid_argument("inv_msg");
+
+ result |= y << offset;
+ offset += sc.radix_storage_bits();
+
+ if (offset >= static_cast<int>(radix_bits))
+ {
+ x.push(result);
+ offset -= radix_bits;
+ result = static_cast<digit_type>(y >> (sc.radix_storage_bits() - offset));
     }
 
- // one last round for the remaining decimal digits
- if (first != last)
+ bits_read += sc.radix_storage_bits();
+ }
+
+ if (result || x.is_uninitialized())
+ x.push(result);
+
+ // right shift bits and reverse the digits
+ const size_type n = bits_read % radix_bits;
+
+ if (n)
+ {
+ const size_type shift = radix_bits - n;
+ const digit_type mask = (digit_type(1) << n) - 1;
+ typename ApInt::iterator b = x.begin();
+ typename ApInt::iterator e = x.end();
+
+ if (b == e)
     {
- digit_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 (size_)
- {
- digit_type carry = ops_type::multiply_by_digit(digits_, digits_, size_,
- static_cast<digit_type>(radix_power));
+ x[0] >>= shift;
+ return;
+ }
 
- carry += ops_type::add_single_digit(digits_, digits_, size_, result);
+ --e;
+ digit_type carry1 = 0;
 
- if (carry)
- push(carry);
- }
- else
- push(result);
+ while (b < e)
+ {
+ const digit_type c1 = *b & mask;
+ digit_type d1 = (*b >> n) | (carry1 << shift);
+ carry1 = c1;
+
+ const digit_type carry2 = *(e-1) & mask;
+ digit_type d2 = (*e >> n) | (carry2 << shift);
+
+ *b = d2;
+ *e = d1;
+
+ ++b;
+ --e;
     }
+
+ // if the number of digits is odd, we need to shift the digit in the middle
+ if (x.size() & 1)
+ *b = (*b >> n) | (carry1 << shift);
   }
+ else
+ std::reverse(x.begin(), x.end());
+
+ x.clamp();
 }
 
+template<class ApInt>
+template<typename RandomAccessIterator>
+void
+from_string_converter<ApInt>::
+convert(ApInt& x,
+ RandomAccessIterator first, RandomAccessIterator last,
+ unsigned radix,
+ std::random_access_iterator_tag) const
+{
+ const sc_type sc(radix);
+
+ //static const char* inv_msg =
+ // "from_string_converter::convert: invalid character";
 
-namespace detail
+ if (is_power_of_two(radix))
+ {
+ const size_type required =
+ (length * sc.radix_storage_bits() + (radix_bits - 1)) / radix_bits;
+
+ x.reserve(required);
+
+ convert_pow2_radix(x, first, last, radix, sc);
+ }
+ else
+ {
+ size_type required;
+
+ // approximate log2(10) = 3.32192809488736234787 with 10/3
+ if (length < std::numeric_limits<size_type>::max() / 10U)
+ required = (10U * length + 2U) / 3U;
+ else
+ required = length / 3U * 10U;
+
+ required = (required + (radix_bits - 1)) / radix_bits;
+
+ x.reserve(required);
+
+ convert_other_radix(x, first, last, radix, sc);
+ }
+}
+
+
+template<class ApInt, bool is_signed = ApInt::is_signed>
+struct sign_prefix;
+
+template<class ApInt> struct sign_prefix<ApInt,false>
+{
+ template<typename OutputIter>
+ static void write(const ApInt&, std::ios_base::fmtflags f, OutputIter& c)
+ {
+ if (f & std::ios_base::showpos)
+ *c++ = '+';
+ }
+};
+
+template<class ApInt> struct sign_prefix<ApInt,true>
+{
+ template<typename OutputIter>
+ static void write(const ApInt& x, std::ios_base::fmtflags f, OutputIter& c)
+ {
+ if (x.is_negative())
+ *c++ = '-';
+ else if (f & std::ios_base::showpos)
+ *c++ = '+';
+ }
+};
+
+
+template<class ApInt>
+struct to_string_converter
 {
- template<typename T, class Alloc>
- struct scoped_ptr : Alloc
+ typedef typename ApInt::size_type size_type;
+ typedef typename ApInt::digit_type digit_type;
+ typedef typename ApInt::traits_type::ops_type ops_type;
+
+ template<typename OutputIter>
+ void convert(const ApInt& x, std::ios_base::fmtflags f, OutputIter c);
+
+ template<class StringT>
+ void convert(StringT&, const ApInt& x, std::ios_base::fmtflags f);
+
+ static bool is_power_of_two(unsigned radix)
   {
- 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); }
+ return (radix & (radix - 1)) == 0;
+ }
+
+ unsigned int radix;
+ size_type total_bits_; // precision of the integer we're converting
+ size_type prefix_length_;
+ size_type number_length_;
+ size_type total_length_;
+
+ enum error_t
+ {
+ err_unsupported_radix,
+ err_out_of_memory,
+ err_no_error
   };
-}
 
+ error_t err;
 
-// 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
+ void check_fmtflags(std::ios_base::fmtflags f);
+
+private:
+
+ typedef sc_constants<ApInt> sc_type;
+
+ static const unsigned radix_bits = ApInt::traits_type::radix_bits;
+
+ static const char* const lowercase_tab_;
+ static const char* const uppercase_tab_;
+ const char* tab_;
+
+ template<typename OutputIter>
+ static void write_sign_prefix(const ApInt& x, std::ios_base::fmtflags f, OutputIter& c)
+ {
+ sign_prefix<ApInt>::write(x, f, c);
+ }
+
+ template<typename OutputIter>
+ void write_radix_prefix(std::ios_base::fmtflags f, OutputIter& c);
+
+ template<typename OutputIter>
+ void convert_pow2_radix(const ApInt& x, const sc_type& sc, OutputIter& c) const;
+
+ template<typename OutputIter>
+ void convert_other_radix(const ApInt& x, const sc_type& sc, OutputIter& c) const;
+
+ void estimate_number_length(const ApInt& x,
+ const sc_type& sc);
+};
+
+
+template<class ApInt>
+const char* const
+to_string_converter<ApInt>::lowercase_tab_ = "0123456789abcdef";
+
+template<class ApInt>
+const char* const
+to_string_converter<ApInt>::uppercase_tab_ = "0123456789ABCDEF";
+
+
+template<class ApInt>
+void
+to_string_converter<ApInt>::
+estimate_number_length(const ApInt& x,
+ const sc_type& sc)
 {
- typedef typename StringT::value_type char_type;
+ total_bits_ = x.precision();
 
- StringT s;
+ // 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();
+
+ if (is_power_of_two(radix))
+ number_length_ = (total_bits_ + (sc.radix_storage_bits() - 1))
+ / sc.radix_storage_bits();
+ // approximate log2(10) with 13/4 = 3.25
+ else if (total_bits_ < std::numeric_limits<size_type>::max() / 4)
+ number_length_ = (total_bits_ * 4 + 12) / 13;
+ else
+ number_length_ = total_bits_ / 13 * 4;
 
- if (is_uninitialized())
- return s;
+ total_length_ = number_length_ + prefix_length_;
+}
 
- digit_type radix;
+template<class ApInt>
+void
+to_string_converter<ApInt>::check_fmtflags(std::ios_base::fmtflags f)
+{
+ prefix_length_ = f & std::ios_base::showbase ? 1 : 0;
 
   if (f & std::ios_base::hex)
+ {
     radix = 16;
+ if (f & std::ios_base::showbase)
+ prefix_length_ += 2;
+ }
   else if (f & std::ios_base::oct)
+ {
     radix = 8;
+ if (f & std::ios_base::showbase)
+ prefix_length_ += 1;
+ }
   else if (f & std::ios_base::dec)
     radix = 10;
   else
- throw std::invalid_argument("mp_int<>::to_string: unsupported radix");
+ err = err_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::uppercase)
+ tab_ = uppercase_tab_;
+ else
+ tab_ = lowercase_tab_;
+}
 
+template<class ApInt>
+template<typename OutputIter>
+void
+to_string_converter<ApInt>::
+write_radix_prefix(std::ios_base::fmtflags f, OutputIter& c)
+{
   if (f & std::ios_base::showbase)
   {
     if (radix == 16)
     {
- *p++ = '0';
+ *c++ = '0';
       if (f & std::ios_base::uppercase)
- *p++ = 'X';
+ *c++ = 'X';
       else
- *p++ = 'x';
+ *c++ = 'x';
     }
     else if (radix == 8)
- *p++ = '0';
+ *c++ = '0';
   }
+}
+
+template<class ApInt>
+template<typename OutputIter>
+void
+to_string_converter<ApInt>::
+convert_pow2_radix(const ApInt& x, const sc_type& sc, OutputIter& c) const
+{
+ const digit_type mask = (digit_type(1) << sc.radix_storage_bits()) - 1;
 
- const int prefix_offset = p - prefix;
+ int offset = total_bits_ % radix_bits;
+ if (!offset)
+ offset = radix_bits;
 
- if (!*this)
+ typename ApInt::const_reverse_iterator d = x.rbegin();
+ for (;;)
   {
- 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;
- }
+ offset -= sc.radix_storage_bits();
+
+ while (offset >= 0)
+ {
+ *c++ = tab_[(*d >> offset) & mask];
+ offset -= sc.radix_storage_bits();
+ }
 
- const detail::string_conversion_constants<mp_int> sc(radix);
- const bool is_power_of_two = (radix & (radix - 1)) == 0;
+ const digit_type partial_value = (*d << -offset) & mask;
 
- 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;
+ if (++d == x.rend())
+ break;
 
- required += prefix_offset;
- detail::scoped_ptr<char_type, typename StringT::allocator_type> sd(required);
+ offset += radix_bits;
+ *c++ = tab_[partial_value | (*d >> offset)];
+ }
+}
+
+template<class ApInt>
+template<typename OutputIter>
+void
+to_string_converter<ApInt>::
+convert_other_radix(const ApInt& x, const sc_type& sc, OutputIter& c) const
+{
+ ApInt tmp = abs(x);
+
+ while (tmp)
+ {
+ digit_type remainder = ops_type::divide_by_digit(tmp.digits(),
+ tmp.digits(),
+ tmp.size(),
+ sc.max_power_value());
+ tmp.clamp_high_digit();
 
- 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 = (digit_type(1) << sc.radix_storage_bits) - 1;
-
- int offset = total_bits % valid_bits;
- if (!offset)
- offset = valid_bits;
-
- const_reverse_iterator d = rbegin();
- for (;;)
+ for (digit_type i = 0; i < sc.max_exponent(); ++i)
     {
- 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)];
+ if (remainder || tmp)
+ *c++ = static_cast<char>('0' + remainder % 10U);
+ remainder /= 10U;
     }
   }
+}
+
+template<class ApInt>
+template<typename OutputIter>
+void
+to_string_converter<ApInt>::convert(const ApInt& x,
+ std::ios_base::fmtflags f,
+ OutputIter c)
+{
+ if (x.is_uninitialized())
+ return;
+
+ write_sign_prefix(x, f, c);
+ write_radix_prefix(f, c);
+
+ if (!x)
+ {
+ if (!(f & std::ios_base::oct))
+ *c = '0';
+ return;
+ }
+
+ const sc_type sc(radix);
+
+ if (is_power_of_two(radix))
+ convert_pow2_radix(x, sc, c);
   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)
- {
- digit_type remainder = ops_type::divide_by_digit(tmp.digits(),
- tmp.digits(),
- tmp.size(),
- sc.max_power_value);
- tmp.clamp_high_digit();
+ std::pair<char*, std::ptrdiff_t> buf =
+ std::get_temporary_buffer<char>(number_length_);
 
- for (digit_type i = 0; i < m; ++i)
- {
- if (remainder || tmp)
- *c++ = static_cast<char_type>('0' + remainder % 10U);
- remainder /= 10U;
- }
+ if (buf.first)
+ {
+ char* ptr = buf.first;
+ convert_other_radix(x, sc, ptr);
+
+ std::reverse_copy(buf.first, ptr, c);
+
+ std::return_temporary_buffer<char>(buf.first);
     }
- std::reverse(sd.ptr + prefix_offset, c);
+ else
+ err = err_out_of_memory;
   }
+}
+
+template<class ApInt>
+template<class StringT>
+void
+to_string_converter<ApInt>::convert(StringT& s,
+ const ApInt& x,
+ std::ios_base::fmtflags f)
+{
+ check_fmtflags(f);
+
+ const sc_type sc(radix);
 
- s.assign(sd.ptr, c);
+ estimate_number_length(x, sc);
+ s.reserve(total_length_);
 
- return s;
+ convert(x, f, std::back_inserter(s));
 }
 
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/detail/string_conversion_constants.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/detail/string_conversion_constants.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,111 +0,0 @@
-// 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/integer/detail/unbounded_int_integral.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/unbounded_int_integral.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,788 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_UNBOUNDED_INT_INTEGRAL_OPS_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_UNBOUNDED_INT_INTEGRAL_OPS_HPP
+
+#include <boost/mp_math/integer/detail/base/unbounded_int_integral.hpp>
+#include <boost/mp_math/integer/detail/unbounded_uint_integral.hpp>
+#include <boost/mp_math/integer/unbounded_uint.hpp>
+
+// Here we optimize interaction with built in integral types.
+// This code is even hairier and more subtle.
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+template<
+ class UnboundedInt,
+ typename IntegralT,
+ bool is_signed = std::numeric_limits<IntegralT>::is_signed
+>
+struct unbounded_int_integral_ops_impl;
+
+
+// 1)
+template<class UnboundedInt>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt,
+ typename UnboundedInt::digit_type,
+ false
+>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef typename unbounded_int_type::digit_type integral_type;
+ typedef typename unbounded_int_type::traits_type traits_type;
+
+ typedef base::unbounded_int_integral_ops<
+ unbounded_int_type, integral_type
+ > base_type;
+
+ typedef unbounded_uint_integral_ops<
+ unbounded_int_type, integral_type
+ > magnitude_type_integral_ops;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(1);
+ base_type::assign(lhs, rhs);
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(lhs.size() + 1);
+ base_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(lhs.size() + 1);
+ base_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs);
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y);
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_type::divide(lhs, rhs);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_type::modulo(lhs, rhs);
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+template<class UnboundedInt>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, typename UnboundedInt::digit_type, false
+>::multiply(unbounded_int_type& lhs, integral_type rhs)
+{
+ if (rhs == 0)
+ {
+ assign(lhs, integral_type(0));
+ return;
+ }
+ else if (rhs == 1)
+ return;
+
+ lhs.reserve(lhs.size() + 1);
+
+ const integral_type carry =
+ traits_type::ops_type::multiply_by_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+
+ if (carry)
+ lhs.push(carry);
+}
+
+template<class UnboundedInt>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, typename UnboundedInt::digit_type, false
+>::multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+{
+ if (y == 0)
+ {
+ assign(z, integral_type(0));
+ return;
+ }
+ else if (y == 1)
+ {
+ z = x;
+ return;
+ }
+
+ z.reserve(x.size() + 1);
+
+ const integral_type carry =
+ traits_type::ops_type::multiply_by_digit(
+ z.digits(), x.digits(), x.size(), y);
+
+ z.set_size(x.size());
+ z.set_sign_bit(x.sign_bit());
+
+ if (carry)
+ z.push(carry);
+}
+
+
+// 2)
+template<class UnboundedInt>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt,
+ typename make_signed<typename UnboundedInt::digit_type>::type,
+ true
+>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef typename make_signed<
+ typename unbounded_int_type::digit_type
+ >::type integral_type;
+
+ typedef typename unbounded_int_type::digit_type unsigned_integral_type;
+
+ typedef base::unbounded_int_integral_ops<
+ unbounded_int_type,
+ integral_type
+ > base_integral_ops_type;
+
+ static bool get_sign_bit(integral_type x)
+ {
+ if (x >= 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ static unsigned_integral_type get_absolute(integral_type x)
+ {
+ if (x >= 0)
+ return static_cast<unsigned_integral_type>(x);
+ else
+ return static_cast<unsigned_integral_type>(-x);
+ }
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(1);
+ base_integral_ops_type::assign(lhs, rhs);
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base_integral_ops_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base_integral_ops_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (rhs >= 0)
+ {
+ lhs.reserve(lhs.size() + 1);
+ base::unbounded_int_integral_ops<
+ unbounded_int_type,
+ unsigned_integral_type
+ >::add(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+ else
+ base::unbounded_int_integral_ops<
+ unbounded_int_type,
+ unsigned_integral_type
+ >::subtract(lhs, static_cast<unsigned_integral_type>(-rhs));
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (rhs >= 0)
+ base_integral_ops_type::subtract(lhs, static_cast<unsigned_integral_type>(rhs));
+ else
+ base_integral_ops_type::add(lhs, static_cast<unsigned_integral_type>(-rhs));
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ unbounded_int_integral_ops_impl<
+ unbounded_int_type,
+ unsigned_integral_type
+ >::multiply(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ unbounded_int_integral_ops_impl<
+ unbounded_int_type,
+ unsigned_integral_type
+ >::multiply(z, x, get_absolute(y));
+ z.set_sign_bit(x.sign_bit() ^ get_sign_bit(y));
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_integral_ops_type::divide(lhs, rhs);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_integral_ops_type::modulo(lhs, rhs);
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_integral_ops_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_integral_ops_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_integral_ops_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+// 3
+template<class UnboundedInt, typename IntegralT>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, false
+>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef typename unbounded_int_type::traits_type traits_type;
+ typedef IntegralT integral_type;
+ typedef std::numeric_limits<integral_type> integral_type_limits;
+
+ typedef base::unbounded_int_integral_ops<
+ unbounded_int_type, integral_type
+ > base_unbounded_int_integral_ops_type;
+
+ typedef base::unbounded_uint_integral_ops<
+ unbounded_int_type, integral_type
+ > magnitude_type_integral_ops;
+
+ static const unsigned radix_bits = traits_type::radix_bits;
+ static const unsigned max_digit_value = traits_type::max_digit_value;
+
+ static const unsigned q =
+ (integral_type_limits::digits + (radix_bits - 1))
+ / radix_bits;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(q);
+ magnitude_type_integral_ops::assign(lhs, rhs);
+ lhs.set_sign_bit(0);
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base_unbounded_int_integral_ops_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base_unbounded_int_integral_ops_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(std::max(lhs.size(), q) + 1);
+ base_unbounded_int_integral_ops_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ base_unbounded_int_integral_ops_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(lhs.size() + q);
+ base_unbounded_int_integral_ops_type::multiply(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ z.reserve(x.size() + q);
+ base_unbounded_int_integral_ops_type::multiply(z, x, y);
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs /= unbounded_int_type(rhs);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs %= unbounded_int_type(rhs);
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(q);
+ base_unbounded_int_integral_ops_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(q);
+ base_unbounded_int_integral_ops_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(q);
+ base_unbounded_int_integral_ops_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+template<class UnboundedInt, typename IntegralT>
+const unsigned unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, false>::q;
+
+
+// 4)
+template<class UnboundedInt, typename IntegralT>
+struct unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, true
+>
+{
+ typedef UnboundedInt unbounded_int_type;
+ typedef typename unbounded_int_type::traits_type traits_type;
+ typedef IntegralT integral_type;
+ typedef typename make_unsigned<
+ integral_type
+ >::type unsigned_integral_type;
+
+ typedef base::unbounded_int<traits_type> unbounded_int_base_type;
+
+ typedef unbounded_uint_integral_ops<
+ unbounded_int_type,
+ unsigned_integral_type
+ > unbounded_uint_integral_ops_type;
+
+ typedef base::unbounded_int_integral_ops<
+ unbounded_int_type,
+ integral_type
+ > base_unbounded_int_integral_ops_type;
+
+ typedef std::numeric_limits<integral_type> integral_type_limits;
+ static const unsigned radix_bits = traits_type::radix_bits;
+ static const unsigned max_digit_value = traits_type::max_digit_value;
+
+ static const unsigned q =
+ (integral_type_limits::digits + (radix_bits - 1))
+ / radix_bits;
+
+ static bool get_sign_bit(integral_type x)
+ {
+ if (x >= 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ static unsigned_integral_type get_absolute(integral_type x)
+ {
+ if (x >= 0)
+ return static_cast<unsigned_integral_type>(x);
+ else
+ return static_cast<unsigned_integral_type>(-x);
+ }
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ unbounded_uint_integral_ops_type::assign(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(get_sign_bit(rhs));
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base::unbounded_int_integral_ops<
+ unbounded_int_type, integral_type>::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return base::unbounded_int_integral_ops<
+ unbounded_int_type, integral_type>::less(lhs, rhs);
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.sign_bit() == get_sign_bit(rhs))
+ unbounded_uint_integral_ops_type::add(lhs, get_absolute(rhs));
+ else
+ subtract_smaller(lhs, get_absolute(rhs), get_sign_bit(rhs));
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ if (lhs.sign_bit() != get_sign_bit(rhs))
+ unbounded_uint_integral_ops_type::add(lhs, get_absolute(rhs));
+ else
+ subtract_smaller(lhs, get_absolute(rhs), ~lhs.sign_bit());
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(lhs.size() + q);
+ base_unbounded_int_integral_ops_type::multiply(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ z.reserve(x.size() + q);
+ base_unbounded_int_integral_ops_type::multiply(z, x, y);
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs /= unbounded_int_type(rhs);
+ //unbounded_uint_integral_ops_type::divide(lhs, get_absolute(rhs));
+ //lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ lhs %= unbounded_int_type(rhs);
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ unbounded_int_integral_ops_impl<
+ UnboundedInt, unsigned_integral_type
+ >::bitwise_or(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() | get_sign_bit(rhs));
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ unbounded_int_integral_ops_impl<
+ UnboundedInt, unsigned_integral_type
+ >::bitwise_and(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() & get_sign_bit(rhs));
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ unbounded_int_integral_ops_impl<
+ UnboundedInt, unsigned_integral_type
+ >::bitwise_xor(lhs, get_absolute(rhs));
+ lhs.set_sign_bit(lhs.sign_bit() ^ get_sign_bit(rhs));
+ }
+
+ static void subtract_smaller(unbounded_int_type& lhs,
+ unsigned_integral_type rhs,
+ bool final_sign);
+};
+
+
+template<class UnboundedInt, typename IntegralT>
+const unsigned unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, true>::q;
+
+
+template<class UnboundedInt, typename IntegralT>
+void
+unbounded_int_integral_ops_impl<
+ UnboundedInt, IntegralT, true
+>::subtract_smaller(unbounded_int_type& lhs,
+ unsigned_integral_type rhs,
+ bool final_sign)
+{
+ static const unsigned radix_bits = traits_type::radix_bits;
+
+ static const unsigned q =
+ (std::numeric_limits<integral_type>::digits + (radix_bits - 1))
+ / radix_bits;
+
+ typedef base::unbounded_uint<traits_type> unbounded_uint_base_type;
+
+ typename traits_type::digit_type tmp_digits[q];
+
+ unbounded_uint_base_type tmp(tmp_digits, q, q);
+
+ base::from_integral_converter<
+ unbounded_uint_base_type, unsigned_integral_type
+ >::convert(tmp, rhs);
+
+ const unbounded_uint_base_type* x;
+ const unbounded_uint_base_type* y;
+
+ if (static_cast<const unbounded_uint_base_type&>(lhs) >= tmp)
+ {
+ x = &lhs;
+ y = &tmp;
+ }
+ else
+ {
+ x = &tmp;
+ y = &lhs;
+ lhs.reserve(tmp.size());
+ lhs.set_sign_bit(final_sign);
+ }
+
+ traits_type::ops_type::sub_smaller_magnitude(
+ lhs.digits(), x->digits(), x->size(),
+ y->digits(), y->size());
+
+ lhs.set_size(x->size());
+ lhs.clamp();
+
+ if (!lhs)
+ lhs.set_sign_bit(0);
+}
+
+
+template<
+ class UnboundedInt,
+ typename IntegralT,
+ bool less_equal =
+ std::numeric_limits<IntegralT>::is_signed ?
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<
+ typename make_signed<
+ typename UnboundedInt::traits_type::digit_type
+ >::type
+ >::digits
+ ):
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<
+ typename UnboundedInt::traits_type::digit_type
+ >::digits
+ )
+>
+struct unbounded_int_integral_ops;
+
+
+// Dispatches integral types that fit into a digit_type by casting it to
+// digit_type or signed digit_type and using the specialization at the top.
+template<
+ class UnboundedInt,
+ typename IntegralT
+>
+struct unbounded_int_integral_ops<UnboundedInt,IntegralT,true>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedInt unbounded_int_type;
+ typedef IntegralT integral_type;
+ typedef typename unbounded_int_type::traits_type traits_type;
+
+ typedef typename mpl::if_<
+ is_signed<IntegralT>,
+ unbounded_int_integral_ops_impl<
+ unbounded_int_type,
+ typename make_signed<
+ typename unbounded_int_type::digit_type
+ >::type
+ >,
+ unbounded_int_integral_ops_impl<
+ unbounded_int_type,
+ typename unbounded_int_type::digit_type
+ >
+ >::type impl_type;
+
+ typedef typename impl_type::integral_type to_integral_type;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, static_cast<to_integral_type>(y));
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, static_cast<to_integral_type>(rhs));
+ }
+};
+
+
+template<
+ class UnboundedInt,
+ typename IntegralT
+>
+struct unbounded_int_integral_ops<UnboundedInt,IntegralT,false>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedInt unbounded_int_type;
+ typedef IntegralT integral_type;
+ typedef typename unbounded_int_type::traits_type traits_type;
+
+ typedef unbounded_int_integral_ops_impl<
+ unbounded_int_type, integral_type
+ > impl_type;
+
+ static void assign(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, rhs);
+ }
+
+ static bool equal(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_int_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, rhs);
+ }
+
+ static void multiply(unbounded_int_type& z,
+ const unbounded_int_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, y);
+ }
+
+ static void divide(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, rhs);
+ }
+
+ static void modulo(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, rhs);
+ }
+
+ static void bitwise_or(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_int_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/unbounded_uint_integral.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/unbounded_uint_integral.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,657 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_UNBOUNDED_UINT_INTEGRAL_OPS_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_UNBOUNDED_UINT_INTEGRAL_OPS_HPP
+
+#include <boost/mp_math/integer/detail/base/unbounded_uint_integral.hpp>
+
+// Here we optimize interaction with built in integral types.
+// This code is even hairier and more subtle.
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+// Generally we will try to dispatch calls to unbounded_uint_integral_ops
+// possibly with a call to reserve() before that. If more optimization is
+// possible by calling reserve() only at certain points inside a function then
+// we reimplement the functionality of the corresponding
+// unbounded_uint_integral_ops function here. That means in any case the
+// functions closely correlate and improvements should be applied to both.
+
+template<
+ class UnboundedUint,
+ typename IntegralT,
+ bool is_signed = std::numeric_limits<IntegralT>::is_signed
+>
+struct unbounded_uint_integral_ops_impl;
+
+
+// 1)
+template<class UnboundedUint>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUint,
+ typename UnboundedUint::digit_type,
+ false
+>
+{
+ typedef UnboundedUint unbounded_uint_type;
+ typedef typename unbounded_uint_type::traits_type traits_type;
+ typedef typename unbounded_uint_type::digit_type integral_type;
+
+ typedef base::unbounded_uint_integral_ops<
+ base::unbounded_uint<traits_type>,
+ integral_type
+ > base_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(1);
+ base_type::assign(lhs, rhs);
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return base_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return base_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(lhs.size() + 1);
+ base_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ base_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs);
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y);
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ base_type::divide(lhs, rhs);
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ base_type::modulo(lhs, rhs);
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ base_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ base_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ base_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+template<class UnboundedUint>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUint, typename UnboundedUint::digit_type, false
+>::multiply(unbounded_uint_type& lhs, integral_type rhs)
+{
+ if (rhs == 0)
+ {
+ assign(lhs, integral_type(0));
+ return;
+ }
+ else if (rhs == 1)
+ return;
+
+ lhs.reserve(lhs.size() + 1);
+
+ const integral_type carry =
+ traits_type::ops_type::multiply_by_digit(
+ lhs.digits(), lhs.digits(), lhs.size(), rhs);
+
+ if (carry)
+ lhs.push(carry);
+}
+
+template<class UnboundedUint>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUint, typename UnboundedUint::digit_type, false
+>::multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+{
+ if (y == 0)
+ {
+ assign(z, integral_type(0));
+ return;
+ }
+ else if (y == 1)
+ {
+ z = x;
+ return;
+ }
+
+ z.reserve(x.size() + 1);
+
+ const integral_type carry =
+ traits_type::ops_type::multiply_by_digit(
+ z.digits(), x.digits(), x.size(), y);
+
+ z.set_size(x.size());
+
+ if (carry)
+ z.push(carry);
+}
+
+
+// 2)
+// just casts to digit_type and dispatches to above specialization
+template<class UnboundedUint>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUint,
+ typename make_signed<typename UnboundedUint::digit_type>::type,
+ true
+>
+{
+ typedef UnboundedUint unbounded_uint_type;
+ typedef typename unbounded_uint_type::traits_type traits_type;
+ typedef typename make_signed<
+ typename unbounded_uint_type::digit_type
+ >::type integral_type;
+
+ typedef typename unbounded_uint_type::digit_type unsigned_integral_type;
+ typedef unbounded_uint_integral_ops_impl<
+ unbounded_uint_type,
+ unsigned_integral_type
+ > impl_type;
+
+ static unsigned_integral_type get_absolute(integral_type x)
+ {
+ if (x >= 0)
+ return static_cast<unsigned_integral_type>(x);
+ else
+ return static_cast<unsigned_integral_type>(-x);
+ }
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, get_absolute(rhs));
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, get_absolute(rhs));
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, get_absolute(rhs));
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, get_absolute(rhs));
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, get_absolute(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, get_absolute(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, get_absolute(y));
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, get_absolute(rhs));
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, get_absolute(rhs));
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, get_absolute(rhs));
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, get_absolute(rhs));
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, get_absolute(rhs));
+ }
+};
+
+
+// 3
+template<class UnboundedUint, typename IntegralT>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUint, IntegralT, false
+>
+{
+ typedef UnboundedUint unbounded_uint_type;
+ typedef typename unbounded_uint_type::traits_type traits_type;
+ typedef IntegralT integral_type;
+ typedef std::numeric_limits<integral_type> integral_type_limits;
+
+ typedef base::unbounded_uint_integral_ops_impl<
+ base::unbounded_uint<traits_type>,
+ integral_type
+ > impl_type;
+
+ static const unsigned radix_bits = traits_type::radix_bits;
+ static const unsigned max_digit_value = traits_type::max_digit_value;
+
+ static const unsigned q =
+ (integral_type_limits::digits + (radix_bits - 1))
+ / radix_bits;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs);
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(std::max(lhs.size(), q) + 1);
+ impl_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(lhs.size() + q);
+ impl_type::multiply(lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ z.reserve(x.size() + q);
+ impl_type::multiply(z, x, y);
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs /= unbounded_uint_type(rhs);
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs %= unbounded_uint_type(rhs);
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(q);
+ impl_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(q);
+ impl_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ lhs.reserve(q);
+ impl_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+template<class UnboundedUint, typename IntegralT>
+const unsigned unbounded_uint_integral_ops_impl<
+ UnboundedUint, IntegralT, false>::q;
+
+
+template<class UnboundedUint, typename IntegralT>
+void
+unbounded_uint_integral_ops_impl<
+ UnboundedUint, IntegralT, false>::assign(unbounded_uint_type& lhs,
+ integral_type rhs)
+{
+ if (rhs <= max_digit_value)
+ {
+ lhs.reserve(1);
+ lhs[0] = static_cast<typename traits_type::digit_type>(rhs);
+ lhs.set_size(1);
+ }
+ else
+ {
+ lhs.reserve(q);
+
+ base::from_integral_converter<
+ unbounded_uint_type, integral_type
+ >::convert(lhs, rhs);
+ }
+}
+
+
+// 4)
+template<class UnboundedUint, typename IntegralT>
+struct unbounded_uint_integral_ops_impl<
+ UnboundedUint, IntegralT, true
+>
+{
+ typedef UnboundedUint unbounded_uint_type;
+ typedef IntegralT integral_type;
+ typedef typename make_unsigned<integral_type>::type unsigned_integral_type;
+ // this is spec 3
+ typedef unbounded_uint_integral_ops_impl<
+ unbounded_uint_type,
+ unsigned_integral_type
+ > impl_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, static_cast<unsigned_integral_type>(y));
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, static_cast<unsigned_integral_type>(rhs));
+ }
+};
+
+
+
+
+template<
+ class UnboundedUint,
+ typename IntegralT,
+ bool less_equal =
+ std::numeric_limits<IntegralT>::is_signed ?
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<
+ typename make_signed<
+ typename UnboundedUint::traits_type::digit_type
+ >::type
+ >::digits
+ ):
+ (
+ std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<
+ typename UnboundedUint::traits_type::digit_type
+ >::digits
+ )
+>
+struct unbounded_uint_integral_ops
+{};
+
+
+// Dispatches integral types that fit into a digit_type by casting it to
+// digit_type or signed digit_type and calling the specializations 1) and 2).
+template<
+ class UnboundedUint,
+ typename IntegralT
+>
+struct unbounded_uint_integral_ops<UnboundedUint,IntegralT,true>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedUint unbounded_uint_type;
+ typedef IntegralT integral_type;
+ typedef typename unbounded_uint_type::traits_type traits_type;
+
+ typedef typename mpl::if_<
+ is_signed<IntegralT>,
+ unbounded_uint_integral_ops_impl<
+ unbounded_uint_type,
+ typename make_signed<
+ typename unbounded_uint_type::digit_type
+ >::type
+ >,
+ unbounded_uint_integral_ops_impl<
+ unbounded_uint_type,
+ typename unbounded_uint_type::digit_type
+ >
+ >::type impl_type;
+
+ typedef typename impl_type::integral_type to_integral_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, static_cast<to_integral_type>(y));
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, static_cast<to_integral_type>(rhs));
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, static_cast<to_integral_type>(rhs));
+ }
+};
+
+
+template<
+ class UnboundedUint,
+ typename IntegralT
+>
+struct unbounded_uint_integral_ops<UnboundedUint,IntegralT,false>
+{
+ BOOST_STATIC_ASSERT(is_integral<IntegralT>::value);
+
+ typedef UnboundedUint unbounded_uint_type;
+ typedef IntegralT integral_type;
+
+ typedef unbounded_uint_integral_ops_impl<
+ unbounded_uint_type, IntegralT
+ > impl_type;
+
+ static void assign(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::assign(lhs, rhs);
+ }
+
+ static bool equal(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::equal(lhs, rhs);
+ }
+
+ static bool less(const unbounded_uint_type& lhs, integral_type rhs)
+ {
+ return impl_type::less(lhs, rhs);
+ }
+
+ static void add(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::add(lhs, rhs);
+ }
+
+ static void subtract(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::subtract(lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::multiply(lhs, rhs);
+ }
+
+ static void multiply(unbounded_uint_type& z,
+ const unbounded_uint_type& x, integral_type y)
+ {
+ impl_type::multiply(z, x, y);
+ }
+
+ static void divide(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::divide(lhs, rhs);
+ }
+
+ static void modulo(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::modulo(lhs, rhs);
+ }
+
+ static void bitwise_or(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_or(lhs, rhs);
+ }
+
+ static void bitwise_and(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_and(lhs, rhs);
+ }
+
+ static void bitwise_xor(unbounded_uint_type& lhs, integral_type rhs)
+ {
+ impl_type::bitwise_xor(lhs, rhs);
+ }
+};
+
+
+
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/div.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/div.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,149 +0,0 @@
-// 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 || !*this)
- return 0;
-
- const bool is_power_of_two = (b & (b-1)) == 0;
-
- if (!is_power_of_two)
- {
- const digit_type remainder =
- ops_type::divide_by_digit(digits(), digits(), size(), b);
-
- clamp_high_digit();
-
- if (!*this)
- set_sign(1);
-
- return remainder;
- }
-
- int i = 0;
- while ((i < valid_bits) && (b != digit_type(1) << i))
- ++i;
-
- const digit_type remainder = digits_[0] & ((digit_type(1) << i) - 1);
- *this >>= i;
- return remainder;
-}
-
-// *this /= 2
-template<class A, class T>
-void mp_int<A,T>::divide_by_2()
-{
- ops_type::divide_by_two(digits(), digits(), size());
-
- clamp_high_digit();
-
- if (!*this)
- set_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 (!*this)
- set_sign(1);
-}
-
-template<class A, class T>
-void divide(const mp_int<A,T>& x, const mp_int<A,T>& y, mp_int<A,T>& q, mp_int<A,T>& r)
-{
- detail::classic_divide(x, y, q, &r);
-}

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/gcd.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,70 +0,0 @@
-// 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_GCD_HPP
-#define BOOST_MP_MATH_MP_INT_GCD_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-
-
-namespace boost {
-namespace mp_math {
-
-// 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)
-{
- // either zero then gcd is the largest
- if (!a)
- return abs(b);
- if (!b)
- 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);
-
- typedef typename mp_int<A,T>::size_type size_type;
-
- // 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);
-
- // divide out powers of two
- u >>= u_lsb;
- v >>= v_lsb;
-
- while (v)
- {
- if (u > v)
- u.swap(v);
-
- v.sub_smaller_magnitude(u);
-
- // Divide out all factors of two
- v >>= v.count_lsb();
- }
-
- // multiply by 2**k which we divided out at the beginning
- u <<= k;
-
- return u;
-}
-
-#ifdef BOOST_HAS_VARIADIC_TMPL
-template<class A, class T, class... MpInts>
-mp_int<A,T> gcd(const mp_int<A,T>& a, const mp_int<A,T>& b, const MpInts&... args)
-{
- return gcd(gcd(a, b), args...);
-}
-#endif
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Added: sandbox/mp_math/boost/mp_math/integer/gmp_integer.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/gmp_integer.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,1449 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_GMP_INTEGER_HPP
+#define BOOST_MP_MATH_INTEGER_GMP_INTEGER_HPP
+
+#include <gmp.h>
+#include <boost/config.hpp>
+#include <boost/mp_math/integer/contexts.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <cstring> // strlen
+#include <iostream>
+#include <limits>
+#include <stdexcept>
+
+namespace boost {
+namespace mp_math {
+
+struct boost_behavior
+{
+ static void bitwise_or(mpz_ptr z, mpz_srcptr x, mpz_srcptr y);
+ static void bitwise_and(mpz_ptr z, mpz_srcptr x, mpz_srcptr y);
+ static void bitwise_xor(mpz_ptr z, mpz_srcptr x, mpz_srcptr y);
+};
+
+
+struct gmp_behavior
+{
+ static void bitwise_or(mpz_ptr z, mpz_srcptr x, mpz_srcptr y)
+ {
+ mpz_ior(z, x, y);
+ }
+
+ static void bitwise_and(mpz_ptr z, mpz_srcptr x, mpz_srcptr y)
+ {
+ mpz_and(z, x, y);
+ }
+
+ static void bitwise_xor(mpz_ptr z, mpz_srcptr x, mpz_srcptr y)
+ {
+ mpz_xor(z, x, y);
+ }
+};
+
+
+template<class Behavior = gmp_behavior>
+class gmp_integer;
+
+
+namespace detail {
+
+template<
+ class B,
+ typename IntegralT,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed,
+ bool FitsIntoLongInt =
+ IsSigned ? (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<signed long int>::digits)
+ : (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<unsigned long int>::digits)
+>
+struct gmp_integer_integral_ops;
+
+
+template<
+ class B,
+ typename IntegralT
+>
+struct gmp_integer_integral_ops<gmp_integer<B>, IntegralT, false, true>
+{
+ typedef gmp_integer<B> gmp_integer_type;
+ typedef IntegralT integral_type;
+
+ static void init(gmp_integer_type& z, integral_type x)
+ {
+ mpz_init_set_ui(z.get_mpz_t(), x);
+ }
+
+ static void assign(gmp_integer_type& z, integral_type x)
+ {
+ mpz_set_ui(z.get_mpz_t(), x);
+ }
+
+ static bool equal(const gmp_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_ui(z.get_mpz_t(), x) == 0;
+ }
+
+ static bool less(const gmp_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_ui(z.get_mpz_t(), x) < 0;
+ }
+
+ static void add(gmp_integer_type& z, integral_type x)
+ {
+ mpz_add_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void subtract(gmp_integer_type& z, integral_type x)
+ {
+ mpz_sub_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void multiply(gmp_integer_type& z, integral_type x)
+ {
+ mpz_mul_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void divide(gmp_integer_type& z, integral_type x)
+ {
+ mpz_tdiv_q_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void modulo(gmp_integer_type& z, integral_type x)
+ {
+ mpz_mod_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void bitwise_or(gmp_integer_type& z, integral_type x);
+ static void bitwise_and(gmp_integer_type& z, integral_type x);
+ static void bitwise_xor(gmp_integer_type& z, integral_type x);
+};
+
+
+template<
+ class B,
+ typename IntegralT
+>
+struct gmp_integer_integral_ops<gmp_integer<B>, IntegralT, true, true>
+{
+ typedef gmp_integer<B> gmp_integer_type;
+ typedef IntegralT integral_type;
+
+ static void init(gmp_integer_type& z, integral_type x)
+ {
+ mpz_init_set_si(z.get_mpz_t(), x);
+ }
+
+ static void assign(gmp_integer_type& z, integral_type x)
+ {
+ mpz_set_si(z.get_mpz_t(), x);
+ }
+
+ static bool equal(const gmp_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_si(z.get_mpz_t(), x) == 0;
+ }
+
+ static bool less(const gmp_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_si(z.get_mpz_t(), x) < 0;
+ }
+
+ static void add(gmp_integer_type& z, integral_type x)
+ {
+ mpz_add_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void subtract(gmp_integer_type& z, integral_type x)
+ {
+ mpz_sub_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void multiply(gmp_integer_type& z, integral_type x)
+ {
+ mpz_mul_si(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void divide(gmp_integer_type& z, integral_type x)
+ {
+ mpz_tdiv_q_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void modulo(gmp_integer_type& z, integral_type x)
+ {
+ mpz_mod_ui(z.get_mpz_t(), z.get_mpz_t(), x);
+ }
+
+ static void bitwise_or(gmp_integer_type& z, integral_type x);
+ static void bitwise_and(gmp_integer_type& z, integral_type x);
+ static void bitwise_xor(gmp_integer_type& z, integral_type x);
+};
+
+
+template<
+ class B,
+ typename IntegralT,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed,
+ bool FitsIntoLongInt =
+ IsSigned ? (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<signed long int>::digits)
+ : (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<unsigned long int>::digits)
+>
+struct gmp_integer_to_integral;
+
+
+template<class B, typename IntegralT>
+struct gmp_integer_to_integral<B, IntegralT, false, true>
+{
+ static IntegralT convert(const gmp_integer<B>& x)
+ {
+ return static_cast<IntegralT>(mpz_get_ui(x.get_mpz_t()));
+ }
+};
+
+
+template<class B, typename IntegralT>
+struct gmp_integer_to_integral<B, IntegralT, true, true>
+{
+ static IntegralT convert(const gmp_integer<B>& x)
+ {
+ return static_cast<IntegralT>(mpz_get_si(x.get_mpz_t()));
+ }
+};
+
+
+
+struct gmp_integer_traits
+{
+ typedef mp_limb_t digit_type;
+ typedef std::size_t size_type;
+
+ static const size_type digit_bits = GMP_LIMB_BITS;
+ static const size_type radix_bits = GMP_NUMB_BITS;
+ static const digit_type max_digit_value = GMP_NUMB_MAX;
+};
+
+
+// Same as gmp_allocated_string in gmp-impl.h, but we can't use it because
+// gmp-impl.h is an internal GMP header and is probably not installed.
+extern "C"
+{
+ typedef void (*gmp_free_func)(void *, size_t);
+}
+
+struct gmp_allocated_string
+{
+ char* str;
+ const std::size_t len;
+
+ gmp_allocated_string(char *s)
+ :
+ str(s), len(std::strlen(s) + 1)
+ {}
+
+ ~gmp_allocated_string()
+ {
+ gmp_free_func f;
+ mp_get_memory_functions (0, 0, &f);
+ (*f)(str, len);
+ }
+};
+
+
+
+} // namespace detail
+
+
+// gmp_original or gmp_boost
+// differences: bitwise ops
+template<class Behavior>
+class gmp_integer
+{
+ mpz_t val_;
+
+public:
+
+ static const bool is_signed = true;
+ static const bool is_bounded = false;
+
+ typedef Behavior behavior_type;
+
+ template<typename IntegralT>
+ struct integral_ops
+ :
+ detail::gmp_integer_integral_ops<gmp_integer<Behavior>, IntegralT>
+ {};
+
+ typedef detail::gmp_integer_traits traits_type;
+
+ typedef traits_type::digit_type digit_type;
+ typedef traits_type::size_type size_type;
+
+ typedef digit_type* iterator;
+ typedef const digit_type* const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ gmp_integer()
+ {
+ mpz_init(val_);
+ }
+
+ template<typename IntegralT>
+ gmp_integer(IntegralT x,
+ typename enable_if<is_integral<IntegralT> >::type* dummy = 0)
+ {
+ integral_ops<IntegralT>::init(*this, x);
+ }
+
+ gmp_integer(const mpz_t& x)
+ {
+ mpz_init_set(val_, x);
+ }
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ gmp_integer(mpz_t&& x)
+ :
+ val_(x)
+ {}
+ #endif
+
+ explicit gmp_integer(const char* s);
+ explicit gmp_integer(const std::string& s);
+
+ gmp_integer(const char* s, std::ios_base::fmtflags);
+ gmp_integer(const std::string& s, std::ios_base::fmtflags);
+
+ gmp_integer(const gmp_integer& copy)
+ {
+ mpz_init_set(val_, copy.val_);
+ }
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ gmp_integer(gmp_integer&& copy)
+ {
+ val_->_mp_alloc = copy.val_->_mp_alloc;
+ val_->_mp_size = copy.val_->_mp_size;
+ val_->_mp_d = copy.val_->_mp_d;
+ copy.val_->_mp_alloc = 0;
+ copy.val_->_mp_size = 0;
+ copy.val_->_mp_d = 0;
+ }
+ #endif
+
+ ~gmp_integer()
+ {
+ mpz_clear(val_);
+ }
+
+ gmp_integer& operator = (const gmp_integer& rhs)
+ {
+ mpz_set(val_, rhs.val_);
+ return *this;
+ }
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ gmp_integer& operator = (gmp_integer&& rhs)
+ {
+ mpz_clear(val_);
+ swap(rhs);
+ return *this;
+ }
+ #endif
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator = (IntegralT x)
+ {
+ integral_ops<IntegralT>::assign(*this, x);
+ return *this;
+ }
+
+ template<typename charT>
+ gmp_integer& operator = (const charT* s)
+ {
+ if (mpz_set_str(val_, s, 0) == 0)
+ return *this;
+ else
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer: operator = (const charT*)");
+ }
+
+ template<typename charT, class traits, class alloc>
+ gmp_integer& operator = (const std::basic_string<charT,traits,alloc>& s)
+ {
+ if (mpz_set_str(val_, s.c_str(), 0) == 0)
+ return *this;
+ else
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer: operator = (const charT*)");
+ }
+
+ template<typename charT>
+ void assign(const charT* s, std::ios_base::fmtflags f)
+ {
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+ if (mpz_set_str(val_, s, radix) == -1)
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer::assign: illformatted string)");
+ }
+
+ // TODO dispatch std::string to mpz_set_string, but dispatch other string
+ // types to detail/string_converter? Could do that but would need support for
+ // NAIL bits.
+ template<typename charT, class traits, class alloc>
+ void assign(const std::basic_string<charT,traits,alloc>& s,
+ std::ios_base::fmtflags f)
+ {
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+ if (mpz_set_str(val_, s.c_str(), radix) == -1)
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer::assign: illformatted string)");
+ }
+
+
+ template<typename RandomAccessIterator>
+ void assign(RandomAccessIterator first, RandomAccessIterator last,
+ std::ios_base::fmtflags);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ void swap(gmp_integer&& other)
+ #else
+ void swap(gmp_integer& other)
+ #endif
+ {
+ mpz_swap(val_, other.val_);
+ }
+
+#ifdef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
+private:
+
+ typedef mpz_t gmp_integer::*unspecified_bool_type;
+
+public:
+
+ operator unspecified_bool_type() const
+ {
+ return mpz_sgn(val_) ? &gmp_integer::val_ : 0;
+ }
+#else
+ explicit operator bool() const { return static_cast<bool>(mpz_sgn(val_)); }
+#endif
+
+ bool is_even() const { return mpz_even_p(val_); }
+ bool is_odd () const { return mpz_odd_p(val_); }
+
+ bool is_positive() const { return mpz_sgn(val_) >= 0; }
+ bool is_negative() const { return mpz_sgn(val_) < 0; }
+
+ // These two functions use the same signature as GMP's mpz_class
+ mpz_ptr get_mpz_t() { return val_; }
+ mpz_srcptr get_mpz_t() const { return val_; }
+
+ size_type size() const { return mpz_size(val_); }
+
+ digit_type* digits() { return val_->_mp_d; }
+ const digit_type* digits() const { return val_->_mp_d; }
+
+ iterator begin() { return digits(); }
+ iterator end () { return digits(); }
+ const_iterator begin() const { return digits(); }
+ const_iterator end () const { return digits() + size(); }
+ const_iterator cbegin() const { return digits(); }
+ const_iterator cend () const { return digits() + size(); }
+ 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()); }
+ const_reverse_iterator crbegin() const { return const_reverse_iterator(end ()); }
+ const_reverse_iterator crend () const { return const_reverse_iterator(begin()); }
+
+ digit_type& operator [] (size_type i) { return val_->_mp_d[i]; }
+ const digit_type& operator [] (size_type i) const { return val_->_mp_d[i]; }
+
+ gmp_integer& operator ++() { mpz_add_ui(val_, val_, 1); return *this; }
+ gmp_integer& operator --() { mpz_sub_ui(val_, val_, 1); return *this; }
+
+ gmp_integer operator ++(int)
+ {
+ gmp_integer tmp;
+ mpz_add_ui(tmp.val_, val_, 1);
+ return tmp;
+ }
+
+ gmp_integer operator --(int)
+ {
+ gmp_integer tmp;
+ mpz_sub_ui(tmp.val_, val_, 1);
+ return tmp;
+ }
+
+ gmp_integer& operator <<= (size_type n)
+ {
+ mpz_mul_2exp(val_, val_, n);
+ return *this;
+ }
+
+ gmp_integer& operator >>= (size_type n)
+ {
+ mpz_tdiv_q_2exp(val_, val_, n);
+ return *this;
+ }
+
+ gmp_integer& operator - () { mpz_neg(val_, val_); return *this; }
+
+ gmp_integer& operator ~ () { mpz_cmp(val_, val_); return *this; }
+
+ gmp_integer& operator += (const gmp_integer& rhs)
+ {
+ mpz_add(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ gmp_integer& operator -= (const gmp_integer& rhs)
+ {
+ mpz_sub(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ gmp_integer& operator *= (const gmp_integer& rhs)
+ {
+ mpz_mul(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ gmp_integer& operator /= (const gmp_integer& rhs)
+ {
+ mpz_tdiv_q(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ gmp_integer& operator %= (const gmp_integer& rhs)
+ {
+ mpz_tdiv_r(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ gmp_integer& operator |= (const gmp_integer& rhs)
+ {
+ behavior_type::bitwise_or(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ gmp_integer& operator &= (const gmp_integer& rhs)
+ {
+ behavior_type::bitwise_and(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ gmp_integer& operator ^= (const gmp_integer& rhs)
+ {
+ behavior_type::bitwise_xor(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator += (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator -= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator *= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator /= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator %= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator |= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator &= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, gmp_integer&>::type
+ operator ^= (IntegralT);
+
+ template<typename IntegralT>
+ IntegralT to_integral() const
+ {
+ return detail::gmp_integer_to_integral<behavior_type, IntegralT>::
+ convert(*this);
+ }
+
+ template<class StringT>
+ StringT to_string(std::ios_base::fmtflags f = std::ios_base::fmtflags()) const
+ {
+ int radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+
+ const detail::gmp_allocated_string tmp(mpz_get_str(0, radix, val_));
+ return StringT(tmp.str, tmp.str + tmp.len - 1);
+ }
+};
+
+
+template<class B>
+gmp_integer<B>::gmp_integer(const char* s)
+{
+ if (*s != '\0')
+ {
+ if (mpz_init_set_str(val_, s, 0))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer::gmp_integer(const char*)");
+ }
+ }
+ else
+ mpz_init(val_);
+}
+
+template<class B>
+gmp_integer<B>::gmp_integer(const char* s, std::ios_base::fmtflags f)
+{
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+
+ if (*s != '\0')
+ {
+ if (mpz_init_set_str(val_, s, radix))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer::"
+ "gmp_integer(const char*, std::ios_base::fmtflags)");
+ }
+ }
+ else
+ mpz_init(val_);
+}
+
+template<class B>
+gmp_integer<B>::gmp_integer(const std::string& s)
+{
+ if (!s.empty())
+ {
+ if (mpz_init_set_str(val_, s.c_str(), 0))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer::gmp_integer(const std::string&)");
+ }
+ }
+ else
+ mpz_init(val_);
+}
+
+template<class B>
+gmp_integer<B>::gmp_integer(const std::string& s, std::ios_base::fmtflags f)
+{
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+
+ if (!s.empty())
+ {
+ if (mpz_init_set_str(val_, s.c_str(), radix))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::gmp_integer::"
+ "gmp_integer(const std::string&, std::ios_base::fmtflags)");
+ }
+ }
+ else
+ mpz_init(val_);
+}
+
+template<class B>
+inline void swap(gmp_integer<B>& lhs, gmp_integer<B>& rhs)
+{
+ lhs.swap(rhs);
+}
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class B>
+inline void swap(gmp_integer<B>&& lhs, gmp_integer<B>& rhs)
+{
+ lhs.swap(rhs);
+}
+template<class B>
+inline void swap(gmp_integer<B>& lhs, gmp_integer<B>&& rhs)
+{
+ lhs.swap(rhs);
+}
+#endif
+
+
+template<class B>
+inline gmp_integer<B>
+operator << (const gmp_integer<B>& x,
+ typename gmp_integer<B>::size_type n)
+{
+ gmp_integer<B> nrv;
+ mpz_mul_2exp(nrv.get_mpz_t(), x.get_mpz_t(), n);
+ return nrv;
+}
+
+template<class B>
+inline gmp_integer<B>
+operator >> (const gmp_integer<B>& x,
+ typename gmp_integer<B>::size_type n)
+{
+ gmp_integer<B> nrv;
+ mpz_tdiv_q_2exp(nrv.get_mpz_t(), x.get_mpz_t(), n);
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator + (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ mpz_add(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator - (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ mpz_sub(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator * (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ mpz_mul(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator / (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ mpz_tdiv_q(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator % (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ mpz_tdiv_r(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator | (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ B::bitwise_or(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator & (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ B::bitwise_and(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+operator ^ (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ gmp_integer<B> nrv;
+ B::bitwise_xor(nrv.get_mpz_t(), lhs.get_mpz_t(), rhs.get_mpz_t());
+ return nrv;
+}
+
+// Arithmetic and bitwise operators involving integral types
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator += (IntegralT rhs)
+{
+ integral_ops<IntegralT>::add(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator -= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::subtract(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator *= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::multiply(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator /= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::divide(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator %= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::modulo(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator |= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_or(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator &= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_and(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B>&>::type
+gmp_integer<B>::operator ^= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_xor(*this, rhs);
+ return *this;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator + (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv += rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator - (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv -= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator * (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv *= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator / (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv /= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator % (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv %= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator | (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv |= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator & (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv &= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, gmp_integer<B> >::type
+operator ^ (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ gmp_integer<B> nrv(lhs);
+ nrv ^= rhs;
+ return nrv;
+}
+
+
+template<class B>
+inline bool operator == (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ return mpz_cmp(lhs.get_mpz_t(), rhs.get_mpz_t()) == 0;
+}
+
+template<class B>
+inline bool operator != (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ return mpz_cmp(lhs.get_mpz_t(), rhs.get_mpz_t()) != 0;
+}
+
+template<class B>
+inline bool operator < (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ return mpz_cmp(lhs.get_mpz_t(), rhs.get_mpz_t()) < 0;
+}
+
+template<class B>
+inline bool operator > (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ return mpz_cmp(lhs.get_mpz_t(), rhs.get_mpz_t()) > 0;
+}
+
+template<class B>
+inline bool operator <= (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ return mpz_cmp(lhs.get_mpz_t(), rhs.get_mpz_t()) <= 0;
+}
+
+template<class B>
+inline bool operator >= (const gmp_integer<B>& lhs, const gmp_integer<B>& rhs)
+{
+ return mpz_cmp(lhs.get_mpz_t(), rhs.get_mpz_t()) >= 0;
+}
+
+// compare unbounded_int to integral
+/*template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_int_integral_ops<
+ gmp_integer<B>, IntegralT>::equal(lhs, rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ return !(lhs == rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator < (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_int_integral_ops<
+ gmp_integer<B>, IntegralT>::less(lhs, rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ return rhs < lhs;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator <= (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ return (lhs < rhs) || (lhs == rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator >= (const gmp_integer<B>& lhs, IntegralT rhs)
+{
+ return !(lhs < rhs);
+}
+
+// compare integral to unbounded_int
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (IntegralT lhs, const gmp_integer<B>& rhs)
+{
+ return rhs == lhs;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (IntegralT lhs, const gmp_integer<B>& rhs)
+{
+ return !(lhs == rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator < (IntegralT lhs, const gmp_integer<B>& rhs)
+{
+ return !(rhs <= lhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (IntegralT lhs, const gmp_integer<B>& rhs)
+{
+ return rhs < lhs;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator <= (IntegralT lhs, const gmp_integer<B>& rhs)
+{
+ return !(rhs < lhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator >= (IntegralT lhs, const gmp_integer<B>& rhs)
+{
+ return rhs <= lhs;
+}*/
+
+// compare unbounded_int to const charT*
+template<class B, typename charT>
+inline bool
+operator == (const gmp_integer<B>& lhs, const charT* rhs)
+{
+ return lhs == gmp_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator != (const gmp_integer<B>& lhs, const charT* rhs)
+{
+ return lhs != gmp_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator < (const gmp_integer<B>& lhs, const charT* rhs)
+{
+ return lhs < gmp_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator > (const gmp_integer<B>& lhs, const charT* rhs)
+{
+ return lhs > gmp_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator <= (const gmp_integer<B>& lhs, const charT* rhs)
+{
+ return lhs <= gmp_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator >= (const gmp_integer<B>& lhs, const charT* rhs)
+{
+ return lhs >= gmp_integer<B>(rhs);
+}
+
+// comparison const charT* to unbounded_int
+template<class B, typename charT>
+inline bool
+operator == (const charT* lhs, const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) == rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator != (const charT* lhs, const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) != rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator < (const charT* lhs, const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) < rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator > (const charT* lhs, const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) > rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator <= (const charT* lhs, const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) <= rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator >= (const charT* lhs, const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) >= rhs;
+}
+
+// compare unbounded_int to basic_string
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator == (const gmp_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs == gmp_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator != (const gmp_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs != gmp_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator < (const gmp_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs < gmp_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator > (const gmp_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs > gmp_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const gmp_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs <= gmp_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const gmp_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs >= gmp_integer<B>(rhs);
+}
+
+// compare basic_string to unbounded_int
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator == (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) == rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator != (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) != rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator < (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) < rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator > (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) > rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) <= rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const gmp_integer<B>& rhs)
+{
+ return gmp_integer<B>(lhs) >= rhs;
+}
+
+// Input/Output
+template<class B, typename charT, class traits>
+std::basic_istream<charT, traits>&
+operator >> (std::basic_istream<charT, traits>& is, gmp_integer<B>&)
+{
+ return is;
+}
+
+template<class B, typename charT, class traits>
+std::basic_ostream<charT, traits>&
+operator << (std::basic_ostream<charT, traits>& os, const gmp_integer<B>& x)
+{
+ return os << x.template to_string<std::string>(os.flags());
+}
+
+
+
+template<class B>
+inline gmp_integer<B> abs(const gmp_integer<B>& x)
+{
+ gmp_integer<B> nrv;
+ mpz_abs(nrv.get_mpz_t(), x.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline gmp_integer<B> gcd(const gmp_integer<B>& x, const gmp_integer<B>& y)
+{
+ gmp_integer<B> nrv;
+ mpz_gcd(nrv.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
+ return nrv;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class B, class... GMPInteger>
+gmp_integer<B> gcd(const gmp_integer<B>& a,
+ const gmp_integer<B>& b,
+ const GMPInteger&... args)
+{
+ return gcd(gcd(a, b), args...);
+}
+#endif
+
+template<class B>
+inline gmp_integer<B> lcm(const gmp_integer<B>& x, const gmp_integer<B>& y)
+{
+ gmp_integer<B> nrv;
+ mpz_lcm(nrv.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
+ return nrv;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class B, class... GMPInteger>
+gmp_integer<B> lcm(const gmp_integer<B>& a,
+ const gmp_integer<B>& b,
+ const GMPInteger&... args)
+{
+ return lcm(lcm(a, b), args...);
+}
+#endif
+
+template<class B>
+inline
+gmp_integer<B>
+pow(const gmp_integer<B>& x, typename gmp_integer<B>::size_type y)
+{
+ gmp_integer<B> nrv;
+ mpz_pow_ui(nrv.get_mpz_t(), x.get_mpz_t(), y);
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B> pow(const gmp_integer<B>& x, const gmp_integer<B>& y)
+{
+ gmp_integer<B> nrv;
+ mpz_pow_ui(nrv.get_mpz_t(), x.get_mpz_t(),
+ y.template to_integral<unsigned long>());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+sqrt(const gmp_integer<B>& x)
+{
+ gmp_integer<B> nrv;
+ mpz_sqrt(nrv.get_mpz_t(), x.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+nth_root(typename gmp_integer<B>::size_type n, const gmp_integer<B>& x)
+{
+ gmp_integer<B> nrv;
+ mpz_root(nrv.get_mpz_t(), x.get_mpz_t(), n);
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+nth_root(const gmp_integer<B>& n, const gmp_integer<B>& x)
+{
+ gmp_integer<B> nrv;
+ mpz_root(nrv.get_mpz_t(), x.get_mpz_t(), n);
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B>
+modinv(const gmp_integer<B>& x, const gmp_integer<B>& m)
+{
+ gmp_integer<B> nrv;
+ if (mpz_invert(nrv.get_mpz_t(), x.get_mpz_t(), m.get_mpz_t()) == 0)
+ throw std::domain_error(
+ "boost::mp_math::modinv: modular inverse does not exist");
+ return nrv;
+}
+
+template<class B>
+inline
+gmp_integer<B> modpow(const gmp_integer<B>& base,
+ const gmp_integer<B>& exp,
+ const gmp_integer<B>& mod,
+ modpow_ctx<gmp_integer<B> >* ctx = 0)
+{
+ gmp_integer<B> nrv;
+ mpz_powm(nrv.get_mpz_t(), base.get_mpz_t(), exp.get_mpz_t(), mod.get_mpz_t());
+ return nrv;
+}
+
+template<class B>
+inline
+int jacobi(const gmp_integer<B>& x, const gmp_integer<B>& y)
+{
+ return mpz_jacobi(x.get_mpz_t(), y.get_mpz_t());
+}
+
+
+
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif

Copied: sandbox/mp_math/boost/mp_math/integer/integer.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/integer.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -3,910 +3,94 @@
 // (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>
+#ifndef BOOST_MP_MATH_INTEGER_INTEGER_HPP
+#define BOOST_MP_MATH_INTEGER_INTEGER_HPP
 
 #include <boost/config.hpp>
-#include <boost/random.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/mp_math/mp_int/detail/div.hpp>
-#include <boost/mp_math/mp_int/detail/string_conversion_constants.hpp>
-#include <boost/mp_math/mp_int/detail/integral_ops.hpp>
-#include <boost/mp_math/mp_int/detail/meta_math.hpp>
-#include <boost/mp_math/mp_int/detail/primitive_ops.hpp>
-
 
 namespace boost {
 namespace mp_math {
 
-template<
- class Allocator,
- class Traits
->
-struct mp_int
-:
- Allocator::template rebind<typename Traits::digit_type>::other
+template<class Type>
+struct integer : Type
 {
-private:
-
- typedef typename Allocator::template
- rebind<typename Traits::digit_type>::other base_allocator_type;
-
-public:
-
- typedef Allocator allocator_type;
- typedef Traits traits_type;
- typedef typename base_allocator_type::size_type size_type;
-
- mp_int();
-
- explicit mp_int(const allocator_type& a);
-
- template<typename IntegralT>
- mp_int(IntegralT,
- const allocator_type& a = allocator_type(),
- typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
-
- template<typename charT>
- mp_int(const charT*, const allocator_type& a = allocator_type());
-
- template<typename charT>
- mp_int(const charT*,
- std::ios_base::fmtflags,
- const allocator_type& a = allocator_type());
-
- template<typename charT, class traits, class Alloc>
- mp_int(const std::basic_string<charT,traits,Alloc>&,
- const allocator_type& a = allocator_type());
-
- template<typename charT, class traits, class Alloc>
- mp_int(const std::basic_string<charT,traits,Alloc>&,
- std::ios_base::fmtflags,
- const allocator_type& a = allocator_type());
-
- template<typename RandomAccessIterator>
- mp_int(RandomAccessIterator first,
- RandomAccessIterator last,
- const allocator_type& a = allocator_type());
-
- template<typename RandomAccessIterator>
- mp_int(RandomAccessIterator first,
- RandomAccessIterator last,
- std::ios_base::fmtflags f,
- const allocator_type& a = allocator_type());
-
- mp_int(const mp_int& copy);
+ typedef Type type;
+ typedef typename type::traits_type traits_type;
+ typedef typename type::digit_type digit_type;
+ typedef typename type::size_type size_type;
+ typedef typename type::iterator iterator;
+ typedef typename type::const_iterator const_iterator;
+ typedef typename type::reverse_iterator reverse_iterator;
+ typedef typename type::const_reverse_iterator const_reverse_iterator;
+
+ integer(){}
+
+ #if !defined(BOOST_NO_VARIADIC_TEMPLATES) && !defined(BOOST_NO_RVALUE_REFERENCES)
+ template<typename... Args>
+ integer(Args&&... args)
+ :
+ type(args...)
+ {}
 
- #ifdef BOOST_HAS_RVALUE_REFS
- mp_int(mp_int&& copy);
- #endif
-
- ~mp_int();
-
- mp_int& operator = (const mp_int& rhs);
+ #else
 
- #ifdef BOOST_HAS_RVALUE_REFS
- mp_int& operator = (mp_int&& rhs);
+ template<typename T1>
+ integer(const T1& t1)
+ : type(t1) {}
+
+ template<typename T1, typename T2>
+ integer(const T1& t1, const T2& t2)
+ : type(t1, t2) {}
+
+ template<typename T1, typename T2, typename T3>
+ integer(const T1& t1, const T2& t2, const T3& t3)
+ : type(t1, t2, t3) {}
+
+ template<typename T1, typename T2, typename T3, typename T4>
+ integer(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
+ : type(t1, t2, t3, t4) {}
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ integer(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5)
+ : type(t1, t2, t3, t4, t5) {}
   #endif
 
- template<typename IntegralT>
- mp_int& operator = (IntegralT rhs);
-
- template<typename charT>
- mp_int& operator = (const charT*);
-
- template<typename charT, class traits, class Alloc>
- mp_int& operator = (const std::basic_string<charT,traits,Alloc>&);
-
- template<typename charT>
- void assign(const charT*, std::ios_base::fmtflags);
-
- 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);
+ template<typename T>
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ integer& operator = (T&& t)
   #else
- void swap(mp_int& other);
+ integer& operator = (const T& t)
   #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);
-
- template<typename charT> mp_int& operator += (const charT*);
- template<typename charT> mp_int& operator -= (const charT*);
- template<typename charT> mp_int& operator *= (const charT*);
- template<typename charT> mp_int& operator /= (const charT*);
- template<typename charT> mp_int& operator %= (const charT*);
- template<typename charT> mp_int& operator |= (const charT*);
- template<typename charT> mp_int& operator &= (const charT*);
- template<typename charT> mp_int& operator ^= (const charT*);
-
- 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 size_type mp_int::*unspecified_bool_type;
-
-public:
-
- operator unspecified_bool_type() const
   {
- return !(size_ == 1 && digits_[0] == 0) ? &mp_int::size_ : 0;
+ type::operator=(t);
+ return *this;
   }
 
- 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);
-
- static const size_type sign_bit =
- size_type(1) << (std::numeric_limits<size_type>::digits - 1U);
-
- 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_ + size_; }
- const_iterator begin() const { return digits_; }
- const_iterator end () const { return digits_ + size_; }
- 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 >= size_)
- throw std::out_of_range("mp_int::at: array subscript out of range");
- return digits_[i];
- }
-
- const digit_type& at(size_type i) const
- {
- if (i >= size_)
- throw std::out_of_range("mp_int::at: array subscript out of range");
- return digits_[i];
- }
-
- void push(digit_type x) { digits_[size_++] = x; }
- void pop() { --size_; }
-
- void zero();
-
- // debug functionality
- void print(bool all=false) const;
- bool test_invariants() const;
-
- bool is_uninitialized() const { return !size_; }
-
- size_type size() const { return size_; }
- size_type capacity() const
- {
- return capacity_ & ~sign_bit;
- }
-
- void set_capacity(size_type c)
- {
- capacity_ &= sign_bit;
- capacity_ |= c;
- }
-
- void set_size(size_type s) { size_ = s; }
-
- int sign() const
- {
- return (capacity_ & sign_bit) ? -1 : 1;
- }
-
- void set_sign(int s)
- {
- if (s == 1)
- capacity_ &= ~sign_bit;
- else
- capacity_ |= sign_bit;
- }
-
- digit_type* digits() { return digits_; }
- const digit_type* digits() const { return digits_; }
-
- void grow_capacity(size_type n);
- void clamp();
- void clamp_high_digit();
-
- int compare_magnitude(const mp_int& rhs) const;
- int compare_to_digit(digit_type) const;
- int compare(const mp_int& rhs) const;
-
- void add_magnitude(const mp_int& rhs);
- void sub_smaller_magnitude(const mp_int& rhs);
-
- 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_by_2();
- digit_type divide_by_3();
- void modulo_2_to_the_power_of(size_type);
- size_type count_lsb() const;
- void shift_right(size_type b, mp_int* remainder);
-
- void pow2(size_type b);
-
- void set_least_significant_bit()
- {
- digits_[0] |= digit_type(1);
- }
-
- void set_bit(size_type bit)
- {
- digits_[bit / valid_bits] |= digit_type(1) << (bit % valid_bits);
- }
-
- void clear_bit(size_type bit)
- {
- digits_[bit / valid_bits] &= ~(digit_type(1) << (bit % valid_bits));
- }
-
- void set_bits(size_type beg, size_type end);
- void clear_bits(size_type beg, size_type end);
-
- void truncate(size_type prec);
-
- size_type precision() const;
-
- void set_precision(size_type bits)
- {
- size_ = (bits + (valid_bits - 1)) / 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<typename Iter>
- void from_string(Iter first, Iter last, unsigned radix);
-
-private:
-
- digit_type* digits_;
- size_type size_, capacity_;
+ operator type& () { return *this; }
+ operator const type& () const { return *this; }
 };
 
 
+template<class Type>
+struct modpow_ctx<integer<Type> >
+:
+ modpow_ctx<Type>
+{};
 
-template<class A, class T>
-void mp_int<A,T>::print(bool all) const
-{
- using std::cout;
- if (is_negative())
- cout << '-';
- cout << size_ << "{";
- for (size_type i = 0; i < size_; ++i)
- {
- cout << static_cast<word_type>(digits_[i]);
- if (i < size_ - 1)
- cout << ",";
- }
- cout << "}";
-
- if (all)
- {
- cout << capacity() - size_ << "{";
- for (size_type i = size_; 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 (size_) // don't test uninitialized mp_ints
- {
- if (size_ > capacity())
- return false;
- if (digits_[size_-1] == 0U)
- return false;
- if (!*this && 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.size_ * sizeof(digit_type));
- size_ = rhs.size_;
- set_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)
- {
- if (digits_)
- this->deallocate(digits_, capacity());
- digits_ = 0;
- size_ = 0;
- capacity_ = 0;
- 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>
-template<typename charT>
-mp_int<A,T>& mp_int<A,T>::operator = (const charT* s)
-{
- size_ = 0;
- init(s, s + std::char_traits<charT>::length(s));
- return *this;
-}
-
-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)
-{
- size_ = 0;
- init(s.begin(), s.end());
- return *this;
-}
-
-template<class A, class T>
-template<typename charT>
-inline void
-mp_int<A,T>::assign(const charT* s, std::ios_base::fmtflags f)
-{
- assign(s, s + std::char_traits<charT>::length(s), f);
-}
-
-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)
-{
- size_ = 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(size_, other.size_);
- std::swap(capacity_, other.capacity_);
-}
-
-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;
- size_ = 1;
- set_sign(1);
-}
-
-template<class A, class T>
-void mp_int<A,T>::grow_capacity(size_type n)
-{
- if (capacity() < n)
- {
- if (n < sign_bit)
- {
- 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) * size_);
- this->deallocate(digits_, capacity());
- digits_ = d;
- set_capacity(n);
- }
- else
- throw std::bad_alloc();
- }
-}
-
-// This is used to ensure that leading zero digits are trimmed.
-template<class A, class T>
-void mp_int<A,T>::clamp()
-{
- while (size_ > 1 && digits_[size_-1] == 0)
- --size_;
-}
-
-// For when we know that only one leading zero digit may exist.
-template<class A, class T>
-inline void mp_int<A,T>::clamp_high_digit()
-{
- if (size_ > 1 && digits_[size_-1] == 0)
- --size_;
-}
-
-// 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 (size_ > rhs.size_)
- return 1;
-
- if (size_ < rhs.size_)
- 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 (size_ > 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
-{
- if (sign() != rhs.sign())
- {
- if (is_negative())
- return -1;
- else
- return 1;
- }
-
- 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(size_ + b);
-
- std::memmove(digits_ + b, digits_, size_ * sizeof(digit_type));
-
- // zero the lower digits
- std::memset(digits_, 0, b * sizeof(digit_type));
-
- size_ += 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 (size_ <= b)
- {
- zero();
- return;
- }
-
- // shift the digits down
- std::memmove(digits_, digits_ + b, (size_ - b) * sizeof(digit_type));
-
- // zero the top digits
- std::memset(digits_ + size_ - b, 0, b * sizeof(digit_type));
-
- // remove excess digits
- size_ -= 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 p = (size_ - 1) * valid_bits;
-
- // take the last digit and count the bits in it
- digit_type q = digits_[size_ - 1];
- while (q > 0U)
- {
- ++p;
- q >>= 1;
- }
- return p;
-}
-
-// 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
- };
-
- if (!*this)
- return 0;
-
- // scan lower digits until non-zero
- size_type x = 0;
- while (x < size_ && 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>
-void mp_int<A,T>::set_bits(size_type beg, size_type end)
-{
- const size_type beg_index = beg / digit_bits;
- const size_type end_index = end / digit_bits;
- const size_type first_bits = beg % digit_bits;
- const size_type last_bits = end % digit_bits;
-
- static const digit_type z = ~digit_type(0);
-
- digit_type mask = z << first_bits;
- if (beg_index == end_index && last_bits)
- mask &= z >> (digit_bits - last_bits);
-
- digits_[beg_index] |= mask;
-
- for (size_type i = beg_index + ((beg % digit_bits) ? 1 : 0); i < end_index; ++i)
- digits_[i] = digit_max;
-
- if (beg_index != end_index && last_bits)
- digits_[end_index] |= z >> (digit_bits - last_bits);
-}
-
-template<class A, class T>
-void mp_int<A,T>::clear_bits(size_type beg, size_type end)
-{
- const size_type beg_index = beg / digit_bits;
- const size_type end_index = end / digit_bits;
- const size_type first_bits = beg % digit_bits;
- const size_type last_bits = end % digit_bits;
-
- static const digit_type z = ~digit_type(0);
-
- digit_type mask;
- if (first_bits)
- mask = z >> (digit_bits - first_bits);
- else
- mask = 0;
-
- if (beg_index == end_index)
- mask |= z << last_bits;
-
- digits_[beg_index] &= mask;
-
- if (beg_index != end_index)
- {
- std::memset(digits_ + beg_index + 1, 0,
- sizeof(digit_type) * (end_index - beg_index - 1));
-
- digits_[end_index] &= z << last_bits;
- }
-}
-
-// don't forget to clamp() after truncating!
-template<class A, class T>
-void mp_int<A,T>::truncate(size_type prec)
-{
- set_precision(prec);
- const size_type last_bits = prec % valid_bits;
- if (last_bits)
- {
- static const digit_type z = ~digit_type(0);
- const digit_type mask = z >> (valid_bits - last_bits);
- digits_[size_ - 1] &= mask;
- }
-}
-
-
-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);
+// returns base^exp % mod
+template<class Type>
+inline
+integer<Type> modpow(const integer<Type>& base,
+ const integer<Type>& exp,
+ const integer<Type>& mod,
+ modpow_ctx<integer<Type> >* ctx = 0)
+{
+ return modpow(static_cast<const Type&>(base),
+ static_cast<const Type&>(exp),
+ static_cast<const Type&>(mod),
+ static_cast<modpow_ctx<Type>*>(ctx));
 }
-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/mod.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/sqr.hpp>
-#include <boost/mp_math/mp_int/sub.hpp>
-#include <boost/mp_math/mp_int/string_conversion.hpp>
 
 } // namespace mp_math
 } // namespace boost

Copied: sandbox/mp_math/boost/mp_math/integer/integer_fwd.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/mp_int_fwd.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/mp_int_fwd.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/integer_fwd.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,23 +1,18 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_MP_INT_FWD_HPP
-#define BOOST_MP_MATH_MP_INT_MP_INT_FWD_HPP
-
-#include <memory>
-#include <boost/mp_math/mp_int/traits.hpp>
+#ifndef BOOST_MP_MATH_MP_INT_INTEGER_FWD_HPP
+#define BOOST_MP_MATH_MP_INT_INTEGER_FWD_HPP
 
+#include <boost/mp_math/integer/unbounded.hpp>
 
 namespace boost {
 namespace mp_math {
 
-template<
- class Allocator = std::allocator<void>,
- class Traits = mp_int_traits<>
->
-struct mp_int;
+template<class Type = unbounded<> >
+struct integer;
 
 } // namespace mp_math
 } // namespace boost

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/jacobi.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,75 +0,0 @@
-// 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_JACOBI_HPP
-#define BOOST_MP_MATH_MP_INT_JACOBI_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-
-
-namespace boost {
-namespace mp_math {
-
-// 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)
- 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[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[0] & 3) == 3) && ((a1[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);
- }
-}
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/lcm.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,47 +0,0 @@
-// 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_LCM_HPP
-#define BOOST_MP_MATH_MP_INT_LCM_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-
-
-namespace boost {
-namespace mp_math {
-
-// computes least common multiple as |a*b|/gcd(a,b)
-template<class A, class T>
-mp_int<A,T> lcm(const mp_int<A,T>& a, const mp_int<A,T>& b)
-{
- mp_int<A,T> result;
-
- if (!a || !b)
- {
- result.zero();
- return result;
- }
-
- result = a / gcd(a, b) * b;
-
- result.set_sign(1);
-
- return result;
-}
-
-#ifdef BOOST_HAS_VARIADIC_TMPL
-template<class A, class T, class... MpInts>
-mp_int<A,T> lcm(const mp_int<A,T>& a, const mp_int<A,T>& b, const MpInts&... args)
-{
- return lcm(lcm(a, b), args...);
-}
-#endif
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Added: sandbox/mp_math/boost/mp_math/integer/libtom_integer.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/libtom_integer.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,1445 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_LIBTOM_INTEGER_HPP
+#define BOOST_MP_MATH_INTEGER_LIBTOM_INTEGER_HPP
+
+#include <tommath.h>
+#include <boost/config.hpp>
+#include <boost/mp_math/integer/contexts.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <cstring> // strlen
+#include <iostream>
+#include <limits>
+#include <stdexcept>
+
+namespace boost {
+namespace mp_math {
+
+struct boost_behavior
+{
+ static void bitwise_or(mp_int* z, mp_int* x, mp_int* y);
+ static void bitwise_and(mp_int* z, mp_int* x, mp_int* y);
+ static void bitwise_xor(mp_int* z, mp_int* x, mp_int* y);
+};
+
+
+struct libtom_behavior
+{
+ static void bitwise_or(mp_int* z, mp_int* x, mp_int* y)
+ {
+ mp_or(x, y, z);
+ }
+
+ static void bitwise_and(mp_int* z, mp_int* x, mp_int* y)
+ {
+ mp_and(x, y, z);
+ }
+
+ static void bitwise_xor(mp_int* z, mp_int* x, mp_int* y)
+ {
+ mp_xor(x, y, z);
+ }
+};
+
+
+template<class Behavior = libtom_behavior>
+class libtom_integer;
+
+
+namespace detail {
+
+template<
+ class B,
+ typename IntegralT,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed,
+ bool FitsIntoLongInt =
+ IsSigned ? (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<signed long int>::digits)
+ : (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<unsigned long int>::digits)
+>
+struct libtom_integer_integral_ops;
+
+
+template<
+ class B,
+ typename IntegralT
+>
+struct libtom_integer_integral_ops<libtom_integer<B>, IntegralT, false, true>
+{
+ typedef libtom_integer<B> libtom_integer_type;
+ typedef IntegralT integral_type;
+
+ static void init(libtom_integer_type& z, integral_type x)
+ {
+ mpz_init_set_ui(z.get_mp_int(), x);
+ }
+
+ static void assign(libtom_integer_type& z, integral_type x)
+ {
+ mpz_set_ui(z.get_mp_int(), x);
+ }
+
+ static bool equal(const libtom_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_ui(z.get_mp_int(), x) == 0;
+ }
+
+ static bool less(const libtom_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_ui(z.get_mp_int(), x) < 0;
+ }
+
+ static void add(libtom_integer_type& z, integral_type x)
+ {
+ mpz_add_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void subtract(libtom_integer_type& z, integral_type x)
+ {
+ mpz_sub_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void multiply(libtom_integer_type& z, integral_type x)
+ {
+ mpz_mul_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void divide(libtom_integer_type& z, integral_type x)
+ {
+ mp_intdiv_q_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void modulo(libtom_integer_type& z, integral_type x)
+ {
+ mpz_mod_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void bitwise_or(libtom_integer_type& z, integral_type x);
+ static void bitwise_and(libtom_integer_type& z, integral_type x);
+ static void bitwise_xor(libtom_integer_type& z, integral_type x);
+};
+
+
+template<
+ class B,
+ typename IntegralT
+>
+struct libtom_integer_integral_ops<libtom_integer<B>, IntegralT, true, true>
+{
+ typedef libtom_integer<B> libtom_integer_type;
+ typedef IntegralT integral_type;
+
+ static void init(libtom_integer_type& z, integral_type x)
+ {
+ mpz_init_set_si(z.get_mp_int(), x);
+ }
+
+ static void assign(libtom_integer_type& z, integral_type x)
+ {
+ mpz_set_si(z.get_mp_int(), x);
+ }
+
+ static bool equal(const libtom_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_si(z.get_mp_int(), x) == 0;
+ }
+
+ static bool less(const libtom_integer_type& z, integral_type x)
+ {
+ return mpz_cmp_si(z.get_mp_int(), x) < 0;
+ }
+
+ static void add(libtom_integer_type& z, integral_type x)
+ {
+ mpz_add_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void subtract(libtom_integer_type& z, integral_type x)
+ {
+ mpz_sub_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void multiply(libtom_integer_type& z, integral_type x)
+ {
+ mpz_mul_si(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void divide(libtom_integer_type& z, integral_type x)
+ {
+ mp_intdiv_q_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void modulo(libtom_integer_type& z, integral_type x)
+ {
+ mpz_mod_ui(z.get_mp_int(), z.get_mp_int(), x);
+ }
+
+ static void bitwise_or(libtom_integer_type& z, integral_type x);
+ static void bitwise_and(libtom_integer_type& z, integral_type x);
+ static void bitwise_xor(libtom_integer_type& z, integral_type x);
+};
+
+
+template<
+ class B,
+ typename IntegralT,
+ bool IsSigned = std::numeric_limits<IntegralT>::is_signed,
+ bool FitsIntoLongInt =
+ IsSigned ? (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<signed long int>::digits)
+ : (std::numeric_limits<IntegralT>::digits <=
+ std::numeric_limits<unsigned long int>::digits)
+>
+struct libtom_integer_to_integral;
+
+
+template<class B, typename IntegralT>
+struct libtom_integer_to_integral<B, IntegralT, false, true>
+{
+ static IntegralT convert(const libtom_integer<B>& x)
+ {
+ return static_cast<IntegralT>(mpz_get_ui(x.get_mp_int()));
+ }
+};
+
+
+template<class B, typename IntegralT>
+struct libtom_integer_to_integral<B, IntegralT, true, true>
+{
+ static IntegralT convert(const libtom_integer<B>& x)
+ {
+ return static_cast<IntegralT>(mpz_get_si(x.get_mp_int()));
+ }
+};
+
+
+
+struct libtom_integer_traits
+{
+ typedef mp_digit digit_type;
+ typedef std::size_t size_type;
+
+ static const size_type digit_bits = GMP_LIMB_BITS;
+ static const size_type radix_bits = GMP_NUMB_BITS;
+ static const digit_type max_digit_value = GMP_NUMB_MAX;
+};
+
+
+// Same as libtom_allocated_string in libtom-impl.h, but we can't use it because
+// libtom-impl.h is an internal GMP header and is probably not installed.
+extern "C"
+{
+ typedef void (*libtom_free_func)(void *, size_t);
+}
+
+struct libtom_allocated_string
+{
+ char* str;
+ const std::size_t len;
+
+ libtom_allocated_string(char *s)
+ :
+ str(s), len(std::strlen(s) + 1)
+ {}
+
+ ~libtom_allocated_string()
+ {
+ libtom_free_func f;
+ mp_get_memory_functions (0, 0, &f);
+ (*f)(str, len);
+ }
+};
+
+
+
+} // namespace detail
+
+
+// libtom_original or libtom_boost
+// differences: bitwise ops
+template<class Behavior>
+class libtom_integer
+{
+ mp_int val_;
+
+public:
+
+ static const bool is_signed = true;
+ static const bool is_bounded = false;
+
+ typedef Behavior behavior_type;
+
+ template<typename IntegralT>
+ struct integral_ops
+ :
+ detail::libtom_integer_integral_ops<libtom_integer<Behavior>, IntegralT>
+ {};
+
+ typedef detail::libtom_integer_traits traits_type;
+
+ typedef traits_type::digit_type digit_type;
+ typedef traits_type::size_type size_type;
+
+ typedef digit_type* iterator;
+ typedef const digit_type* const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ libtom_integer()
+ {
+ mp_init(&val_);
+ }
+
+ template<typename IntegralT>
+ libtom_integer(IntegralT x,
+ typename enable_if<is_integral<IntegralT> >::type* dummy = 0)
+ {
+ integral_ops<IntegralT>::init(*this, x);
+ }
+
+ libtom_integer(const mp_int& x)
+ {
+ mp_init_copy(&val_, &x);
+ }
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ libtom_integer(mp_int&& x)
+ :
+ val_(x)
+ {}
+ #endif
+
+ explicit libtom_integer(const char* s);
+ explicit libtom_integer(const std::string& s);
+
+ libtom_integer(const char* s, std::ios_base::fmtflags);
+ libtom_integer(const std::string& s, std::ios_base::fmtflags);
+
+ libtom_integer(const libtom_integer& copy)
+ {
+ mp_init_copy(&val_, &copy.val_);
+ }
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ libtom_integer(libtom_integer&& copy)
+ {
+ val_.alloc = copy.val_.alloc;
+ val_.used = copy.val_.used;
+ val_.dp = copy.val_.dp;
+ copy.val_.alloc = 0;
+ copy.val_.used = 0;
+ copy.val_.dp = 0;
+ }
+ #endif
+
+ ~libtom_integer()
+ {
+ mp_clear(&val_);
+ }
+
+ libtom_integer& operator = (const libtom_integer& rhs)
+ {
+ mp_copy(&rhs.val_, &val);
+ return *this;
+ }
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ libtom_integer& operator = (libtom_integer&& rhs)
+ {
+ mp_clear(&val_);
+ swap(rhs);
+ return *this;
+ }
+ #endif
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator = (IntegralT x)
+ {
+ integral_ops<IntegralT>::assign(*this, x);
+ return *this;
+ }
+
+ template<typename charT>
+ libtom_integer& operator = (const charT* s)
+ {
+ if (mpz_set_str(val_, s, 0) == 0)
+ return *this;
+ else
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer: operator = (const charT*)");
+ }
+
+ template<typename charT, class traits, class alloc>
+ libtom_integer& operator = (const std::basic_string<charT,traits,alloc>& s)
+ {
+ if (mpz_set_str(val_, s.c_str(), 0) == 0)
+ return *this;
+ else
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer: operator = (const charT*)");
+ }
+
+ template<typename charT>
+ void assign(const charT* s, std::ios_base::fmtflags f)
+ {
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+ if (mp_read_radix(&val_, s, radix) == -1)
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer::assign: illformatted string)");
+ }
+
+ // TODO dispatch std::string to mpz_set_string, but dispatch other string
+ // types to detail/string_converter? Could do that but would need support for
+ // NAIL bits.
+ template<typename charT, class traits, class alloc>
+ void assign(const std::basic_string<charT,traits,alloc>& s,
+ std::ios_base::fmtflags f)
+ {
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+ if (mp_read_radix(&val_, s.c_str(), radix) == -1)
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer::assign: illformatted string)");
+ }
+
+
+ template<typename RandomAccessIterator>
+ void assign(RandomAccessIterator first, RandomAccessIterator last,
+ std::ios_base::fmtflags);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ void swap(libtom_integer&& other)
+ #else
+ void swap(libtom_integer& other)
+ #endif
+ {
+ mp_exch(&val_, &other.val_);
+ }
+
+#ifdef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
+private:
+
+ typedef mp_int libtom_integer::*unspecified_bool_type;
+
+public:
+
+ operator unspecified_bool_type() const
+ {
+ return mp_iszero(&val_) ? 0 : &libtom_integer::val_;
+ }
+#else
+ explicit operator bool() const { return static_cast<bool>(mp_iszero(&val_)); }
+#endif
+
+ bool is_even() const { return mp_iseven(&val_); }
+ bool is_odd () const { return mp_isodd(&val_); }
+
+ bool is_positive() const { return val_.sign >= 0; }
+ bool is_negative() const { return val_.sign < 0; }
+
+ // These two functions use the same signature as GMP's mpz_class
+ mp_int& get_mp_int() { return val_; }
+ const mp_int& get_mp_int() const { return val_; }
+
+ size_type size() const { return statc_cast<size_type>(val_.used); }
+
+ digit_type* digits() { return val_.dp; }
+ const digit_type* digits() const { return val_.dp; }
+
+ iterator begin() { return digits(); }
+ iterator end () { return digits(); }
+ const_iterator begin() const { return digits(); }
+ const_iterator end () const { return digits() + size(); }
+ const_iterator cbegin() const { return digits(); }
+ const_iterator cend () const { return digits() + size(); }
+ 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()); }
+ const_reverse_iterator crbegin() const { return const_reverse_iterator(end ()); }
+ const_reverse_iterator crend () const { return const_reverse_iterator(begin()); }
+
+ digit_type& operator [] (size_type i) { return val_.dp[i]; }
+ const digit_type& operator [] (size_type i) const { return val_.dp[i]; }
+
+ libtom_integer& operator ++() { mp_add_d(&val_, 1, &val_); return *this; }
+ libtom_integer& operator --() { mp_sub_d(&val_, 1, &val_); return *this; }
+
+ libtom_integer operator ++(int)
+ {
+ libtom_integer tmp;
+ mp_add_d(&val_, 1, &tmp.val_);
+ return tmp;
+ }
+
+ libtom_integer operator --(int)
+ {
+ libtom_integer tmp;
+ mp_sub_d(&val_, 1, &tmp.val_);
+ return tmp;
+ }
+
+ libtom_integer& operator <<= (size_type n)
+ {
+ mp_mul_2d(&val_, n, &val_);
+ return *this;
+ }
+
+ libtom_integer& operator >>= (size_type n)
+ {
+ mp_mul_2d(&val_, n, &val_, 0);
+ return *this;
+ }
+
+ libtom_integer& operator - () { mp_neg(&val_, &val_); return *this; }
+
+ libtom_integer& operator ~ () { mpz_cmp(val_, val_); return *this; }
+
+ libtom_integer& operator += (const libtom_integer& rhs)
+ {
+ mp_add(&val_, &rhs.val_, &val_);
+ return *this;
+ }
+
+ libtom_integer& operator -= (const libtom_integer& rhs)
+ {
+ mp_sub(&val_, &rhs.val_, &val_);
+ return *this;
+ }
+
+ libtom_integer& operator *= (const libtom_integer& rhs)
+ {
+ mp_mul(&val_, &rhs.val_, &val_);
+ return *this;
+ }
+
+ libtom_integer& operator /= (const libtom_integer& rhs)
+ {
+ mp_div(&val_, &rhs.val_, &val_, 0);
+ return *this;
+ }
+
+ libtom_integer& operator %= (const libtom_integer& rhs)
+ {
+ mp_div(&val_, &rhs.val_, 0, &val_);
+ return *this;
+ }
+
+ libtom_integer& operator |= (const libtom_integer& rhs)
+ {
+ behavior_type::bitwise_or(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ libtom_integer& operator &= (const libtom_integer& rhs)
+ {
+ behavior_type::bitwise_and(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ libtom_integer& operator ^= (const libtom_integer& rhs)
+ {
+ behavior_type::bitwise_xor(val_, val_, rhs.val_);
+ return *this;
+ }
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator += (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator -= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator *= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator /= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator %= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator |= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator &= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, libtom_integer&>::type
+ operator ^= (IntegralT);
+
+ template<typename IntegralT>
+ IntegralT to_integral() const
+ {
+ return detail::libtom_integer_to_integral<behavior_type, IntegralT>::
+ convert(*this);
+ }
+
+ template<class StringT>
+ StringT to_string(std::ios_base::fmtflags f = std::ios_base::fmtflags()) const
+ {
+ int radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+
+ const detail::libtom_allocated_string tmp(mpz_get_str(0, radix, val_));
+ return StringT(tmp.str, tmp.str + tmp.len - 1);
+ }
+};
+
+
+template<class B>
+libtom_integer<B>::libtom_integer(const char* s)
+{
+ mp_init(&val_);
+ if (*s != '\0')
+ {
+ if (mpz_init_set_str(val_, s, 0))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer::libtom_integer(const char*)");
+ }
+ }
+}
+
+template<class B>
+libtom_integer<B>::libtom_integer(const char* s, std::ios_base::fmtflags f)
+{
+ mp_init(&val_);
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+
+ if (*s != '\0')
+ {
+ if (mpz_init_set_str(val_, s, radix))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer::"
+ "libtom_integer(const char*, std::ios_base::fmtflags)");
+ }
+ }
+}
+
+template<class B>
+libtom_integer<B>::libtom_integer(const std::string& s)
+{
+ mp_init(&val_);
+ if (!s.empty())
+ {
+ if (mpz_init_set_str(val_, s.c_str(), 0))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer::libtom_integer(const std::string&)");
+ }
+ }
+}
+
+template<class B>
+libtom_integer<B>::libtom_integer(const std::string& s, std::ios_base::fmtflags f)
+{
+ mp_init(&val_);
+ unsigned radix;
+ if (f & std::ios_base::hex)
+ radix = 16;
+ else if (f & std::ios_base::oct)
+ radix = 8;
+ else
+ radix = 10;
+
+ if (!s.empty())
+ {
+ if (mpz_init_set_str(val_, s.c_str(), radix))
+ {
+ if (val_->_mp_d)
+ mpz_clear(val_);
+ throw std::invalid_argument(
+ "boost::mp_math::libtom_integer::"
+ "libtom_integer(const std::string&, std::ios_base::fmtflags)");
+ }
+ }
+}
+
+template<class B>
+inline void swap(libtom_integer<B>& lhs, libtom_integer<B>& rhs)
+{
+ lhs.swap(rhs);
+}
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class B>
+inline void swap(libtom_integer<B>&& lhs, libtom_integer<B>& rhs)
+{
+ lhs.swap(rhs);
+}
+template<class B>
+inline void swap(libtom_integer<B>& lhs, libtom_integer<B>&& rhs)
+{
+ lhs.swap(rhs);
+}
+#endif
+
+
+template<class B>
+inline libtom_integer<B>
+operator << (const libtom_integer<B>& x,
+ typename libtom_integer<B>::size_type n)
+{
+ libtom_integer<B> nrv;
+ mpz_mul_2exp(nrv.get_mp_int(), x.get_mp_int(), n);
+ return nrv;
+}
+
+template<class B>
+inline libtom_integer<B>
+operator >> (const libtom_integer<B>& x,
+ typename libtom_integer<B>::size_type n)
+{
+ libtom_integer<B> nrv;
+ mp_intdiv_q_2exp(nrv.get_mp_int(), x.get_mp_int(), n);
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator + (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ mp_add(&lhs.get_mp_int(), &rhs.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator - (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ mp_sub(&lhs.get_mp_int(), &rhs.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator * (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ mp_mul(&lhs.get_mp_int(), &rhs.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator / (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ mp_div(&lhs.get_mp_int(), &rhs.get_mp_int(), &nrv.get_mp_int(), 0);
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator % (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ mp_div(&lhs.get_mp_int(), &rhs.get_mp_int(), 0, &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator | (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ B::bitwise_or(nrv.get_mp_int(), lhs.get_mp_int(), rhs.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator & (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ B::bitwise_and(nrv.get_mp_int(), lhs.get_mp_int(), rhs.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+operator ^ (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ libtom_integer<B> nrv;
+ B::bitwise_xor(nrv.get_mp_int(), lhs.get_mp_int(), rhs.get_mp_int());
+ return nrv;
+}
+
+// Arithmetic and bitwise operators involving integral types
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator += (IntegralT rhs)
+{
+ integral_ops<IntegralT>::add(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator -= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::subtract(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator *= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::multiply(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator /= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::divide(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator %= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::modulo(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator |= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_or(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator &= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_and(*this, rhs);
+ return *this;
+}
+
+template<class B>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B>&>::type
+libtom_integer<B>::operator ^= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_xor(*this, rhs);
+ return *this;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator + (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv += rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator - (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv -= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator * (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv *= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator / (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv /= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator % (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv %= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator | (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv |= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator & (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv &= rhs;
+ return nrv;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, libtom_integer<B> >::type
+operator ^ (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ libtom_integer<B> nrv(lhs);
+ nrv ^= rhs;
+ return nrv;
+}
+
+
+template<class B>
+inline bool operator == (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ return mp_cmp(&lhs.get_mp_int(), &rhs.get_mp_int()) == MP_EQ;
+}
+
+template<class B>
+inline bool operator != (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ return mp_cmp(&lhs.get_mp_int(), &rhs.get_mp_int()) != MP_EQ;
+}
+
+template<class B>
+inline bool operator < (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ return mp_cmp(&lhs.get_mp_int(), &rhs.get_mp_int()) == MP_LT;
+}
+
+template<class B>
+inline bool operator > (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ return mp_cmp(&lhs.get_mp_int(), &rhs.get_mp_int()) == MP_GT;
+}
+
+template<class B>
+inline bool operator <= (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ return mp_cmp(&lhs.get_mp_int(), &rhs.get_mp_int()) <= 0;
+}
+
+template<class B>
+inline bool operator >= (const libtom_integer<B>& lhs, const libtom_integer<B>& rhs)
+{
+ return mp_cmp(&lhs.get_mp_int(), &rhs.get_mp_int()) >= 0;
+}
+
+// compare unbounded_int to integral
+/*template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_int_integral_ops<
+ libtom_integer<B>, IntegralT>::equal(lhs, rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ return !(lhs == rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator < (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_int_integral_ops<
+ libtom_integer<B>, IntegralT>::less(lhs, rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ return rhs < lhs;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator <= (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ return (lhs < rhs) || (lhs == rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator >= (const libtom_integer<B>& lhs, IntegralT rhs)
+{
+ return !(lhs < rhs);
+}
+
+// compare integral to unbounded_int
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (IntegralT lhs, const libtom_integer<B>& rhs)
+{
+ return rhs == lhs;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (IntegralT lhs, const libtom_integer<B>& rhs)
+{
+ return !(lhs == rhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator < (IntegralT lhs, const libtom_integer<B>& rhs)
+{
+ return !(rhs <= lhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (IntegralT lhs, const libtom_integer<B>& rhs)
+{
+ return rhs < lhs;
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator <= (IntegralT lhs, const libtom_integer<B>& rhs)
+{
+ return !(rhs < lhs);
+}
+
+template<class B, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator >= (IntegralT lhs, const libtom_integer<B>& rhs)
+{
+ return rhs <= lhs;
+}*/
+
+// compare unbounded_int to const charT*
+template<class B, typename charT>
+inline bool
+operator == (const libtom_integer<B>& lhs, const charT* rhs)
+{
+ return lhs == libtom_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator != (const libtom_integer<B>& lhs, const charT* rhs)
+{
+ return lhs != libtom_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator < (const libtom_integer<B>& lhs, const charT* rhs)
+{
+ return lhs < libtom_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator > (const libtom_integer<B>& lhs, const charT* rhs)
+{
+ return lhs > libtom_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator <= (const libtom_integer<B>& lhs, const charT* rhs)
+{
+ return lhs <= libtom_integer<B>(rhs);
+}
+
+template<class B, typename charT>
+inline bool
+operator >= (const libtom_integer<B>& lhs, const charT* rhs)
+{
+ return lhs >= libtom_integer<B>(rhs);
+}
+
+// comparison const charT* to unbounded_int
+template<class B, typename charT>
+inline bool
+operator == (const charT* lhs, const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) == rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator != (const charT* lhs, const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) != rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator < (const charT* lhs, const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) < rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator > (const charT* lhs, const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) > rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator <= (const charT* lhs, const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) <= rhs;
+}
+
+template<class B, typename charT>
+inline bool
+operator >= (const charT* lhs, const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) >= rhs;
+}
+
+// compare unbounded_int to basic_string
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator == (const libtom_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs == libtom_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator != (const libtom_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs != libtom_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator < (const libtom_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs < libtom_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator > (const libtom_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs > libtom_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const libtom_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs <= libtom_integer<B>(rhs);
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const libtom_integer<B>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs >= libtom_integer<B>(rhs);
+}
+
+// compare basic_string to unbounded_int
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator == (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) == rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator != (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) != rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator < (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) < rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator > (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) > rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) <= rhs;
+}
+
+template<class B, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const libtom_integer<B>& rhs)
+{
+ return libtom_integer<B>(lhs) >= rhs;
+}
+
+// Input/Output
+template<class B, typename charT, class traits>
+std::basic_istream<charT, traits>&
+operator >> (std::basic_istream<charT, traits>& is, libtom_integer<B>&)
+{
+ return is;
+}
+
+template<class B, typename charT, class traits>
+std::basic_ostream<charT, traits>&
+operator << (std::basic_ostream<charT, traits>& os, const libtom_integer<B>& x)
+{
+ return os << x.template to_string<std::string>(os.flags());
+}
+
+
+
+template<class B>
+inline libtom_integer<B> abs(const libtom_integer<B>& x)
+{
+ libtom_integer<B> nrv;
+ mp_abs(&x.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline libtom_integer<B> gcd(const libtom_integer<B>& x, const libtom_integer<B>& y)
+{
+ libtom_integer<B> nrv;
+ mp_gcd(&x.get_mp_int(), &y.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class B, class... LTMInteger>
+libtom_integer<B> gcd(const libtom_integer<B>& a,
+ const libtom_integer<B>& b,
+ const LTMInteger&... args)
+{
+ return gcd(gcd(a, b), args...);
+}
+#endif
+
+template<class B>
+inline libtom_integer<B> lcm(const libtom_integer<B>& x, const libtom_integer<B>& y)
+{
+ libtom_integer<B> nrv;
+ mp_lcm(&x.get_mp_int(), &y.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class B, class... LTMInteger>
+libtom_integer<B> lcm(const libtom_integer<B>& a,
+ const libtom_integer<B>& b,
+ const LTMInteger&... args)
+{
+ return lcm(lcm(a, b), args...);
+}
+#endif
+
+template<class B>
+inline
+libtom_integer<B>
+pow(const libtom_integer<B>& x, typename libtom_integer<B>::digit_type y)
+{
+ libtom_integer<B> nrv;
+ mp_expt_d(&x.get_mp_int(), y, &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B> pow(const libtom_integer<B>& x, const libtom_integer<B>& y)
+{
+ libtom_integer<B> nrv;
+ mp_expt_d(&x.get_mp_int(),
+ y.template to_integral<unsigned long>(),
+ &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+sqrt(const libtom_integer<B>& x)
+{
+ libtom_integer<B> nrv;
+ mp_sqrt(&x.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+nth_root(typename libtom_integer<B>::digit_type n, const libtom_integer<B>& x)
+{
+ libtom_integer<B> nrv;
+ mp_n_root(&x.get_mp_int(), n, &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+nth_root(const libtom_integer<B>& n, const libtom_integer<B>& x)
+{
+ libtom_integer<B> nrv;
+ mp_n_root(&x.get_mp_int(), n, &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B>
+modinv(const libtom_integer<B>& x, const libtom_integer<B>& m)
+{
+ libtom_integer<B> nrv;
+ mp_invmod(&x.get_mp_int(), &m.get_mp_int(), &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+libtom_integer<B> modpow(const libtom_integer<B>& base,
+ const libtom_integer<B>& exp,
+ const libtom_integer<B>& mod,
+ modpow_ctx<libtom_integer<B> >* ctx = 0)
+{
+ libtom_integer<B> nrv;
+ mp_exptmod(&base.get_mp_int(), &exp.get_mp_int(), &mod.get_mp_int(),
+ &nrv.get_mp_int());
+ return nrv;
+}
+
+template<class B>
+inline
+int jacobi(const libtom_integer<B>& x, const libtom_integer<B>& y)
+{
+ int j;
+ mp_jacobi(&x.get_mp_int(), &y.get_mp_int(), &j);
+ return j;
+}
+
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/mod.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/mod.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,27 +0,0 @@
-// 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 % 2**b
-template<class A, class T>
-void mp_int<A,T>::modulo_2_to_the_power_of(size_type b)
-{
- // if modulus >= *this then return
- if (b >= size_ * valid_bits)
- return;
-
- // zero digits above the last digit of the modulus
- const size_type offset = (b / valid_bits) + ((b % valid_bits) == 0 ? 0 : 1);
- std::memset(digits_ + offset, 0, sizeof(digit_type) * (size_ - offset));
-
- // clear remaining high bits
- const digit_type mask = (1 << (static_cast<digit_type>(b % valid_bits))) - 1;
- digits_[b / valid_bits] &= mask;
-
- clamp();
-
- if (!*this)
- set_sign(1);
-}
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/modinv.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/modinv.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,41 +0,0 @@
-// 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_MODINV_HPP
-#define BOOST_MP_MATH_MP_INT_MODINV_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-#include <boost/mp_math/mp_int/detail/modinv.hpp>
-
-
-namespace boost {
-namespace mp_math {
-
-
-// hac 14.61, pp608
-// returns the modular multiplicative inverse x of a (mod m) such that
-// x*a = 1 (mod m) =>
-// a^-1 = x (mod m)
-// The inverse exists only if a and m are coprime (i.e. gcd(a,m) = 1).
-// If no inverse exists this function will throw std::domain_error.
-template<class A, class T>
-mp_int<A,T> modinv(const mp_int<A,T>& a, const mp_int<A,T>& m)
-{
- if (m.is_negative() || !m)
- throw std::domain_error("modinv: modulus is negative or zero");
-
- // if the modulus is odd we can use a faster routine
- if (m.is_odd())
- return detail::odd_modinv(a, m);
- else
- return detail::even_modinv(a, m);
-}
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/modpow.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/modpow.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,70 +0,0 @@
-// 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_MODPOW_HPP
-#define BOOST_MP_MATH_MP_INT_MODPOW_HPP
-
-#include <boost/mp_math/mp_int/modpow_ctx.hpp>
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-#include <boost/mp_math/mp_int/detail/modpow.hpp>
-#include <boost/mp_math/mp_int/detail/modular_reduction.hpp>
-
-namespace boost {
-namespace mp_math {
-
-// z = base^exp % mod
-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,
- modpow_ctx<A,T>* ctx = 0)
-{
- if (mod.is_negative())
- throw std::domain_error("modpow: modulus must be positive");
-
- typedef modpow_ctx<A,T> ctx_t;
-
- ctx_t tmp_ctx;
-
- if (!ctx)
- {
- tmp_ctx.detect_modulus_type(mod);
- tmp_ctx.precalculate(mod);
- ctx = &tmp_ctx;
- }
- else
- {
- if (!ctx->precalculated)
- {
- ctx->detect_modulus_type(mod);
- ctx->precalculate(mod);
- }
- }
-
- if (exp.is_negative())
- return modpow(modinv(base, mod), abs(exp), mod, ctx);
-
- switch (ctx->modulus_type)
- {
- case ctx_t::mod_restricted_dr:
- return detail::montgomery_modpow(base, exp, mod, 1, ctx->rho);
- case ctx_t::mod_unrestricted_dr:
- return detail::montgomery_modpow(base, exp, mod, 2, ctx->rho);
- case ctx_t::mod_unrestricted_dr_slow:
- return detail::barret_modpow (base, exp, mod, 1, ctx->mu);
- case ctx_t::mod_odd:
- return detail::montgomery_modpow(base, exp, mod, 0, ctx->rho);
- case ctx_t::mod_generic:
- default:
- return detail::barret_modpow (base, exp, mod, 0, ctx->mu);
- }
-}
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/modpow_ctx.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/modpow_ctx.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,185 +0,0 @@
-// 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_MODPOW_CTX_HPP
-#define BOOST_MP_MATH_MP_INT_MODPOW_CTX_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-
-namespace boost {
-namespace mp_math {
-
-
-// r = x mod m given x and m
-template<class A, class T>
-struct modpow_ctx
-{
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::word_type word_type;
- typedef typename mp_int<A,T>::size_type size_type;
-
- // dr means diminished radix
- enum modulus_type_t
- { // R is our radix, i.e. digit_max
- mod_restricted_dr, // m = R**k - d; d <= R
- mod_unrestricted_dr, // m = 2**k - d; d <= R
- mod_unrestricted_dr_slow, // m = 2**k - d; d < d**(k/2)
- mod_odd,
- mod_generic
- }modulus_type;
-
- modpow_ctx() : precalculated(false){}
-
- modulus_type_t do_detect(const mp_int<A,T>& m) const;
-
- void detect_modulus_type(const mp_int<A,T>& m)
- {
- modulus_type = do_detect(m);
- }
-
- void precalculate(const mp_int<A,T>& m);
-
- mp_int<A,T> mu;
- digit_type rho;
- bool precalculated;
-};
-
-
-template<class A, class T>
-typename modpow_ctx<A,T>::modulus_type_t
-modpow_ctx<A,T>::do_detect(const mp_int<A,T>& m) const
-{
- if (m.size() == 1)
- return mod_unrestricted_dr;
-
- typename mp_int<A,T>::size_type count = 0;
-
- const int bits = m.precision() % mp_int<A,T>::valid_bits;
-
- if (!bits && m[m.size()-1] == mp_int<A,T>::digit_max)
- ++count;
-
- for (typename mp_int<A,T>::const_reverse_iterator d = m.rbegin() + 1;
- d != m.rend(); ++d)
- {
- if (*d != mp_int<A,T>::digit_max)
- break;
- else
- ++count;
- }
-
- // if all bits are set
- if (count == m.size() - 1)
- return mod_restricted_dr;
-
- // if all bits until the most significant digit are set
- if (count == m.size() - 2)
- {
- bool all_bits_set = true;
-
- // handle the remaining bits in the most significant digit
- typename mp_int<A,T>::digit_type mask = 1;
- for (int i = 0; i < bits; ++i)
- {
- if ((m[m.size()-1] & mask) == 0)
- {
- all_bits_set = false;
- break;
- }
- mask <<= 1;
- }
- if (all_bits_set)
- return mod_unrestricted_dr;
- }
-
- // if more than half of the bits are set
- if (count >= m.size() / 2)
- return mod_unrestricted_dr_slow;
-
- if (m.is_odd())
- return mod_odd;
-
- return mod_generic;
-}
-
-template<class A, class T>
-void modpow_ctx<A,T>::precalculate(const mp_int<A,T>& m)
-{
- typedef typename mp_int<A,T>::digit_type digit_type;
- typedef typename mp_int<A,T>::word_type word_type;
-
- switch (modulus_type)
- {
- case mod_restricted_dr:
- {
- rho = (word_type(1) << static_cast<word_type>(mp_int<A,T>::valid_bits))
- - static_cast<word_type>(m[0]);
- break;
- }
- case mod_unrestricted_dr:
- {
- const size_type p = m.precision();
-
- mp_int<A,T> tmp;
- tmp.pow2(p);
- tmp.sub_smaller_magnitude(m);
-
- rho = tmp[0];
- break;
- }
- case mod_unrestricted_dr_slow:
- {
- mp_int<A,T> tmp;
-
- tmp.pow2(m.precision());
- mu = tmp - m;
- break;
- }
- case mod_odd:
- {
- assert(m.is_odd());
-
- // 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 = m[0];
-
- static const typename mp_int<A,T>::size_type S =
- sizeof(digit_type) * std::numeric_limits<unsigned char>::digits;
-
- 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
- rho = (word_type(1) << (static_cast<word_type>(mp_int<A,T>::valid_bits))) - x;
- break;
- }
- case mod_generic:
- {
- // mu = b**2k/m
- mu.pow2(m.size() * 2 * mp_int<A,T>::digit_bits);
- mu /= m;
- break;
- }
- }
- precalculated = true;
-}
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/mp_int.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,914 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#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/type_traits/is_integral.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/mp_math/mp_int/detail/div.hpp>
-#include <boost/mp_math/mp_int/detail/string_conversion_constants.hpp>
-#include <boost/mp_math/mp_int/detail/integral_ops.hpp>
-#include <boost/mp_math/mp_int/detail/meta_math.hpp>
-#include <boost/mp_math/mp_int/detail/primitive_ops.hpp>
-
-
-namespace boost {
-namespace mp_math {
-
-template<
- class Allocator,
- class Traits
->
-struct mp_int
-:
- Allocator::template rebind<typename Traits::digit_type>::other
-{
-private:
-
- typedef typename Allocator::template
- rebind<typename Traits::digit_type>::other base_allocator_type;
-
-public:
-
- typedef Allocator allocator_type;
- typedef Traits traits_type;
- typedef typename base_allocator_type::size_type size_type;
-
- mp_int();
-
- explicit mp_int(const allocator_type& a);
-
- template<typename IntegralT>
- mp_int(IntegralT,
- const allocator_type& a = allocator_type(),
- typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
-
- template<typename charT>
- mp_int(const charT*, const allocator_type& a = allocator_type());
-
- template<typename charT>
- mp_int(const charT*,
- std::ios_base::fmtflags,
- const allocator_type& a = allocator_type());
-
- template<typename charT, class traits, class Alloc>
- mp_int(const std::basic_string<charT,traits,Alloc>&,
- const allocator_type& a = allocator_type());
-
- template<typename charT, class traits, class Alloc>
- mp_int(const std::basic_string<charT,traits,Alloc>&,
- std::ios_base::fmtflags,
- const allocator_type& a = allocator_type());
-
- template<typename RandomAccessIterator>
- mp_int(RandomAccessIterator first,
- RandomAccessIterator last,
- const allocator_type& a = allocator_type());
-
- template<typename RandomAccessIterator>
- mp_int(RandomAccessIterator first,
- RandomAccessIterator last,
- std::ios_base::fmtflags f,
- const allocator_type& a = allocator_type());
-
- mp_int(const mp_int& copy);
-
- #ifdef BOOST_HAS_RVALUE_REFS
- mp_int(mp_int&& copy);
- #endif
-
- ~mp_int();
-
- mp_int& operator = (const mp_int& rhs);
-
- #ifdef BOOST_HAS_RVALUE_REFS
- mp_int& operator = (mp_int&& rhs);
- #endif
-
- template<typename IntegralT>
- mp_int& operator = (IntegralT rhs);
-
- template<typename charT>
- mp_int& operator = (const charT*);
-
- template<typename charT, class traits, class Alloc>
- mp_int& operator = (const std::basic_string<charT,traits,Alloc>&);
-
- template<typename charT>
- void assign(const charT*, std::ios_base::fmtflags);
-
- 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);
-
- template<typename charT> mp_int& operator += (const charT*);
- template<typename charT> mp_int& operator -= (const charT*);
- template<typename charT> mp_int& operator *= (const charT*);
- template<typename charT> mp_int& operator /= (const charT*);
- template<typename charT> mp_int& operator %= (const charT*);
- template<typename charT> mp_int& operator |= (const charT*);
- template<typename charT> mp_int& operator &= (const charT*);
- template<typename charT> mp_int& operator ^= (const charT*);
-
- 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 size_type mp_int::*unspecified_bool_type;
-
-public:
-
- operator unspecified_bool_type() const
- {
- return !(size_ == 1 && digits_[0] == 0) ? &mp_int::size_ : 0;
- }
-
- 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);
-
- static const size_type sign_bit =
- size_type(1) << (std::numeric_limits<size_type>::digits - 1U);
-
- 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_ + size_; }
- const_iterator begin() const { return digits_; }
- const_iterator end () const { return digits_ + size_; }
- 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 >= size_)
- throw std::out_of_range("mp_int::at: array subscript out of range");
- return digits_[i];
- }
-
- const digit_type& at(size_type i) const
- {
- if (i >= size_)
- throw std::out_of_range("mp_int::at: array subscript out of range");
- return digits_[i];
- }
-
- void push(digit_type x) { digits_[size_++] = x; }
- void pop() { --size_; }
-
- void zero();
-
- // debug functionality
- void print(bool all=false) const;
- bool test_invariants() const;
-
- bool is_uninitialized() const { return !size_; }
-
- size_type size() const { return size_; }
- size_type capacity() const
- {
- return capacity_ & ~sign_bit;
- }
-
- void set_capacity(size_type c)
- {
- capacity_ &= sign_bit;
- capacity_ |= c;
- }
-
- void set_size(size_type s) { size_ = s; }
-
- int sign() const
- {
- return (capacity_ & sign_bit) ? -1 : 1;
- }
-
- void set_sign(int s)
- {
- if (s == 1)
- capacity_ &= ~sign_bit;
- else
- capacity_ |= sign_bit;
- }
-
- digit_type* digits() { return digits_; }
- const digit_type* digits() const { return digits_; }
-
- void grow_capacity(size_type n);
- void clamp();
- void clamp_high_digit();
-
- int compare_magnitude(const mp_int& rhs) const;
- int compare_to_digit(digit_type) const;
- int compare(const mp_int& rhs) const;
-
- void add_magnitude(const mp_int& rhs);
- void sub_smaller_magnitude(const mp_int& rhs);
-
- 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_by_2();
- digit_type divide_by_3();
- void modulo_2_to_the_power_of(size_type);
- size_type count_lsb() const;
- void shift_right(size_type b, mp_int* remainder);
-
- void pow2(size_type b);
-
- void set_least_significant_bit()
- {
- digits_[0] |= digit_type(1);
- }
-
- void set_bit(size_type bit)
- {
- digits_[bit / valid_bits] |= digit_type(1) << (bit % valid_bits);
- }
-
- void clear_bit(size_type bit)
- {
- digits_[bit / valid_bits] &= ~(digit_type(1) << (bit % valid_bits));
- }
-
- void set_bits(size_type beg, size_type end);
- void clear_bits(size_type beg, size_type end);
-
- void truncate(size_type prec);
-
- size_type precision() const;
-
- void set_precision(size_type bits)
- {
- size_ = (bits + (valid_bits - 1)) / 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<typename Iter>
- void from_string(Iter first, Iter last, unsigned radix);
-
-private:
-
- digit_type* digits_;
- size_type size_, capacity_;
-};
-
-
-
-template<class A, class T>
-void mp_int<A,T>::print(bool all) const
-{
- using std::cout;
- if (is_negative())
- cout << '-';
- cout << size_ << "{";
- for (size_type i = 0; i < size_; ++i)
- {
- cout << static_cast<word_type>(digits_[i]);
- if (i < size_ - 1)
- cout << ",";
- }
- cout << "}";
-
- if (all)
- {
- cout << capacity() - size_ << "{";
- for (size_type i = size_; 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 (size_) // don't test uninitialized mp_ints
- {
- if (size_ > capacity())
- return false;
- if (digits_[size_-1] == 0U)
- return false;
- if (!*this && 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.size_ * sizeof(digit_type));
- size_ = rhs.size_;
- set_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)
- {
- if (digits_)
- this->deallocate(digits_, capacity());
- digits_ = 0;
- size_ = 0;
- capacity_ = 0;
- 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>
-template<typename charT>
-mp_int<A,T>& mp_int<A,T>::operator = (const charT* s)
-{
- size_ = 0;
- init(s, s + std::char_traits<charT>::length(s));
- return *this;
-}
-
-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)
-{
- size_ = 0;
- init(s.begin(), s.end());
- return *this;
-}
-
-template<class A, class T>
-template<typename charT>
-inline void
-mp_int<A,T>::assign(const charT* s, std::ios_base::fmtflags f)
-{
- assign(s, s + std::char_traits<charT>::length(s), f);
-}
-
-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)
-{
- size_ = 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(size_, other.size_);
- std::swap(capacity_, other.capacity_);
-}
-
-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;
- size_ = 1;
- set_sign(1);
-}
-
-template<class A, class T>
-void mp_int<A,T>::grow_capacity(size_type n)
-{
- if (capacity() < n)
- {
- if (n < sign_bit)
- {
- 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) * size_);
- this->deallocate(digits_, capacity());
- digits_ = d;
- set_capacity(n);
- }
- else
- throw std::bad_alloc();
- }
-}
-
-// This is used to ensure that leading zero digits are trimmed.
-template<class A, class T>
-void mp_int<A,T>::clamp()
-{
- while (size_ > 1 && digits_[size_-1] == 0)
- --size_;
-}
-
-// For when we know that only one leading zero digit may exist.
-template<class A, class T>
-inline void mp_int<A,T>::clamp_high_digit()
-{
- if (size_ > 1 && digits_[size_-1] == 0)
- --size_;
-}
-
-// 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 (size_ > rhs.size_)
- return 1;
-
- if (size_ < rhs.size_)
- 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 (size_ > 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
-{
- if (sign() != rhs.sign())
- {
- if (is_negative())
- return -1;
- else
- return 1;
- }
-
- 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(size_ + b);
-
- std::memmove(digits_ + b, digits_, size_ * sizeof(digit_type));
-
- // zero the lower digits
- std::memset(digits_, 0, b * sizeof(digit_type));
-
- size_ += 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 (size_ <= b)
- {
- zero();
- return;
- }
-
- // shift the digits down
- std::memmove(digits_, digits_ + b, (size_ - b) * sizeof(digit_type));
-
- // zero the top digits
- std::memset(digits_ + size_ - b, 0, b * sizeof(digit_type));
-
- // remove excess digits
- size_ -= 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 p = (size_ - 1) * valid_bits;
-
- // take the last digit and count the bits in it
- digit_type q = digits_[size_ - 1];
- while (q > 0U)
- {
- ++p;
- q >>= 1;
- }
- return p;
-}
-
-// 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
- };
-
- if (!*this)
- return 0;
-
- // scan lower digits until non-zero
- size_type x = 0;
- while (x < size_ && 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>
-void mp_int<A,T>::set_bits(size_type beg, size_type end)
-{
- const size_type beg_index = beg / digit_bits;
- const size_type end_index = end / digit_bits;
- const size_type first_bits = beg % digit_bits;
- const size_type last_bits = end % digit_bits;
-
- static const digit_type z = ~digit_type(0);
-
- digit_type mask = z << first_bits;
- if (beg_index == end_index && last_bits)
- mask &= z >> (digit_bits - last_bits);
-
- digits_[beg_index] |= mask;
-
- for (size_type i = beg_index + ((beg % digit_bits) ? 1 : 0); i < end_index; ++i)
- digits_[i] = digit_max;
-
- if (beg_index != end_index && last_bits)
- digits_[end_index] |= z >> (digit_bits - last_bits);
-}
-
-template<class A, class T>
-void mp_int<A,T>::clear_bits(size_type beg, size_type end)
-{
- const size_type beg_index = beg / digit_bits;
- const size_type end_index = end / digit_bits;
- const size_type first_bits = beg % digit_bits;
- const size_type last_bits = end % digit_bits;
-
- static const digit_type z = ~digit_type(0);
-
- digit_type mask;
- if (first_bits)
- mask = z >> (digit_bits - first_bits);
- else
- mask = 0;
-
- if (beg_index == end_index)
- mask |= z << last_bits;
-
- digits_[beg_index] &= mask;
-
- if (beg_index != end_index)
- {
- std::memset(digits_ + beg_index + 1, 0,
- sizeof(digit_type) * (end_index - beg_index - 1));
-
- digits_[end_index] &= z << last_bits;
- }
-}
-
-// don't forget to clamp() after truncating!
-template<class A, class T>
-void mp_int<A,T>::truncate(size_type prec)
-{
- set_precision(prec);
- const size_type last_bits = prec % valid_bits;
- if (last_bits)
- {
- static const digit_type z = ~digit_type(0);
- const digit_type mask = z >> (valid_bits - last_bits);
- digits_[size_ - 1] &= mask;
- }
-}
-
-
-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/mod.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/sqr.hpp>
-#include <boost/mp_math/mp_int/sub.hpp>
-#include <boost/mp_math/mp_int/string_conversion.hpp>
-
-} // namespace mp_math
-} // namespace boost
-
-#endif

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/mp_int_fwd.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/mp_int_fwd.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,26 +0,0 @@
-// 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_FWD_HPP
-#define BOOST_MP_MATH_MP_INT_MP_INT_FWD_HPP
-
-#include <memory>
-#include <boost/mp_math/mp_int/traits.hpp>
-
-
-namespace boost {
-namespace mp_math {
-
-template<
- class Allocator = std::allocator<void>,
- class Traits = mp_int_traits<>
->
-struct mp_int;
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/mul.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/mul.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,361 +0,0 @@
-// 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(size_ + 1);
-
- const digit_type carry =
- ops_type::multiply_by_digit(digits(), digits(), size(), x);
-
- if (carry)
- push(carry);
-}
-
-/* *this *= 2 */
-template<class A, class T>
-void mp_int<A,T>::multiply_by_2()
-{
- grow_capacity(size_ + 1);
-
- const digit_type carry =
- ops_type::multiply_by_two(digits(), digits(), size());
-
- if (carry)
- push(carry);
-}
-
-
-// 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(size_, b.size_) / 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(size_, b.size_) / 2;
-
- // allocate memory
- x0.grow_capacity(B);
- x1.grow_capacity(size_ + b.size_);
- y0.grow_capacity(B);
- y1.grow_capacity(b.size_ - B + 1);
-
- // set size_ count
- x0.size_ = y0.size_ = B;
- x1.size_ = size_ - B;
- y1.size_ = b.size_ - 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 * ( size_ - B));
- std::memcpy(y1.digits_, b.digits_ + B, s * (b.size_ - 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.size_ = digs;
-
- // compute the digits of the product directly
- for (size_type i = 0; i < size_; ++i)
- {
- digit_type carry = 0;
-
- // limit ourselves to making digs digits of output
- const size_type pb = std::min(b.size_, 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[i+j])
- + static_cast<word_type>(digits_[i])
- * static_cast<word_type>(b[j])
- + static_cast<word_type>(carry);
-
- // the new column is the lower part of the result
- tmp[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[i+pb] = carry;
- }
-
- tmp.clamp();
-
- if (!tmp)
- tmp.set_sign(1);
-
- swap(tmp);
-}
-
-// FIXME no routine seems to use this
-//
-// multiplies |a| * |b| and does not compute the lower num 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 num)
-{
- mp_int tmp;
- tmp.grow_capacity(size_ + b.size_ + 1);
- tmp.size_ = size_ + b.size_ + 1;
- std::memset(tmp.digits_, 0, sizeof(digit_type) * tmp.size_);
-
- for (size_type i = 0; i < size_; ++i)
- {
- iterator dst = tmp.begin() + num;
- const_iterator z = b.begin() + (num - i);
- digit_type carry = 0;
-
- for (size_type j = num - i; j < b.size_; ++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)
- tmp.set_sign(1);
-
- swap(tmp);
-}
-
-
-// this is a modified version of fast_s_mul_digs that only produces
-// output digits *above* num. 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 num)
-{
- mul_high_digits(b, num);
-}
-

Modified: sandbox/mp_math/boost/mp_math/integer/numeric_limits.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/numeric_limits.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/numeric_limits.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,28 +1,146 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
+#ifndef BOOST_MP_MATH_INTEGER_NUMERIC_LIMITS_HPP
+#define BOOST_MP_MATH_INTEGER_NUMERIC_LIMITS_HPP
+
+#include <limits>
+
 namespace std
 {
 
+template<class Alloc, class Traits>
+class numeric_limits<
+ boost::mp_math::unbounded_uint<Alloc,Traits>
+>
+{
+ typedef boost::mp_math::unbounded_uint<Alloc,Traits> int_type;
+
+public:
+
+ static const bool is_specialized = true;
+
+ static int_type min() throw() { return int_type(0U); }
+ static int_type max() throw() { return int_type(0U); }
+
+ static const int digits = 0;
+ static const int digits10 = 0;
+ static const bool is_signed = false;
+ static const bool is_integer = true;
+ static const bool is_exact = true;
+ static const int radix = 0;
+
+ // This is a Boost extension since the radix member above cannot hold the true
+ // radix.
+ static const typename int_type::digit_type max_radix_value =
+ int_type::max_digit_value;
+
+ static int_type epsilon () throw() { return int_type(0U); }
+ static int_type round_error() throw() { return int_type(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 int_type infinity () throw() { return int_type(0U); }
+ static int_type quiet_NaN () throw() { return int_type(0U); }
+ static int_type signaling_NaN() throw() { return int_type(0U); }
+ static int_type denorm_min () throw() { return int_type(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;
+};
+
+
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::is_specialized;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_uint<A,T> >::digits;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_uint<A,T> >::digits10;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::is_signed;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::is_integer;
 template<class A, class T>
-class numeric_limits<boost::mp_math::mp_int<A,T> >
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::is_exact;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_uint<A,T> >::radix;
+template<class A, class T>
+const typename boost::mp_math::unbounded_uint<A,T>::digit_type
+numeric_limits<boost::mp_math::unbounded_uint<A,T> >::max_radix_value;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_uint<A,T> >::min_exponent;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_uint<A,T> >::min_exponent10;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_uint<A,T> >::max_exponent;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_uint<A,T> >::max_exponent10;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::has_infinity;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::has_quiet_NaN;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::has_signaling_NaN;
+template<class A, class T>
+const float_denorm_style numeric_limits<boost::mp_math::unbounded_uint<A,T> >::has_denorm;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::is_iec559;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::is_bounded;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::is_modulo;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::traps;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_uint<A,T> >::tinyness_before;
+template<class A, class T>
+const float_round_style numeric_limits<boost::mp_math::unbounded_uint<A,T> >::round_style;
+
+
+template<class Alloc, class Traits>
+class numeric_limits<
+ boost::mp_math::unbounded_int<Alloc,Traits>
+>
 {
+ typedef boost::mp_math::unbounded_int<Alloc,Traits> int_type;
+
 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 int_type min() throw() { return int_type(0U); }
+ static int_type max() throw() { return int_type(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 radix = 0;
+
+ // This is a Boost extension since the radix member above cannot hold the true
+ // radix.
+ static const typename int_type::digit_type max_radix_value =
+ int_type::max_digit_value;
+
+ static int_type epsilon () throw() { return int_type(0U); }
+ static int_type round_error() throw() { return int_type(0U); }
 
   static const int min_exponent = 0;
   static const int min_exponent10 = 0;
@@ -34,19 +152,278 @@
   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 int_type infinity () throw() { return int_type(0U); }
+ static int_type quiet_NaN () throw() { return int_type(0U); }
+ static int_type signaling_NaN() throw() { return int_type(0U); }
+ static int_type denorm_min () throw() { return int_type(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 traps = false;
   static const bool tinyness_before = false;
   static const float_round_style round_style = round_toward_zero;
 };
 
+
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::is_specialized;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_int<A,T> >::digits;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_int<A,T> >::digits10;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::is_signed;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::is_integer;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::is_exact;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_int<A,T> >::radix;
+template<class A, class T>
+const typename boost::mp_math::unbounded_int<A,T>::digit_type
+numeric_limits<boost::mp_math::unbounded_int<A,T> >::max_radix_value;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_int<A,T> >::min_exponent;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_int<A,T> >::min_exponent10;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_int<A,T> >::max_exponent;
+template<class A, class T>
+const int numeric_limits<boost::mp_math::unbounded_int<A,T> >::max_exponent10;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::has_infinity;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::has_quiet_NaN;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::has_signaling_NaN;
+template<class A, class T>
+const float_denorm_style numeric_limits<boost::mp_math::unbounded_int<A,T> >::has_denorm;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::is_iec559;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::is_bounded;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::is_modulo;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::traps;
+template<class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded_int<A,T> >::tinyness_before;
+template<class A, class T>
+const float_round_style numeric_limits<boost::mp_math::unbounded_int<A,T> >::round_style;
+
+
+template<bool Signed, class Alloc, class Traits>
+class numeric_limits<
+ boost::mp_math::unbounded<Signed,Alloc,Traits>
+>
+{
+ typedef boost::mp_math::unbounded<Signed,Alloc,Traits> int_type;
+
+public:
+
+ static const bool is_specialized = true;
+
+ static int_type min() throw() { return int_type(0U); }
+ static int_type max() throw() { return int_type(0U); }
+
+ static const int digits = 0;
+ static const int digits10 = 0;
+ static const bool is_signed = Signed;
+ static const bool is_integer = true;
+ static const bool is_exact = true;
+ static const int radix = 0;
+
+ // This is a Boost extension since the radix member above cannot hold the true
+ // radix.
+ static const typename int_type::digit_type max_radix_value =
+ int_type::max_digit_value;
+
+ static int_type epsilon () throw() { return int_type(0U); }
+ static int_type round_error() throw() { return int_type(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 int_type infinity () throw() { return int_type(0U); }
+ static int_type quiet_NaN () throw() { return int_type(0U); }
+ static int_type signaling_NaN() throw() { return int_type(0U); }
+ static int_type denorm_min () throw() { return int_type(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;
+};
+
+
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::is_specialized;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::unbounded<S,A,T> >::digits;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::unbounded<S,A,T> >::digits10;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::is_signed;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::is_integer;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::is_exact;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::unbounded<S,A,T> >::radix;
+template<bool S, class A, class T>
+const typename boost::mp_math::unbounded<S,A,T>::digit_type
+numeric_limits<boost::mp_math::unbounded<S,A,T> >::max_radix_value;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::unbounded<S,A,T> >::min_exponent;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::unbounded<S,A,T> >::min_exponent10;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::unbounded<S,A,T> >::max_exponent;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::unbounded<S,A,T> >::max_exponent10;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::has_infinity;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::has_quiet_NaN;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::has_signaling_NaN;
+template<bool S, class A, class T>
+const float_denorm_style numeric_limits<boost::mp_math::unbounded<S,A,T> >::has_denorm;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::is_iec559;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::is_bounded;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::is_modulo;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::traps;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::unbounded<S,A,T> >::tinyness_before;
+template<bool S, class A, class T>
+const float_round_style numeric_limits<boost::mp_math::unbounded<S,A,T> >::round_style;
+
+
+template<bool Signed, class Alloc, class Traits>
+class numeric_limits<
+ boost::mp_math::integer<
+ boost::mp_math::unbounded<Signed,Alloc,Traits>
+ >
+>
+{
+ typedef boost::mp_math::integer<
+ boost::mp_math::unbounded<Signed,Alloc,Traits>
+ > int_type;
+
+public:
+
+ static const bool is_specialized = true;
+
+ static int_type min() throw() { return int_type(0U); }
+ static int_type max() throw() { return int_type(0U); }
+
+ static const int digits = 0;
+ static const int digits10 = 0;
+ static const bool is_signed = Signed;
+ static const bool is_integer = true;
+ static const bool is_exact = true;
+ static const int radix = 0;
+
+ // This is a Boost extension since the radix member above cannot hold the true
+ // radix.
+ static const typename int_type::digit_type max_radix_value =
+ int_type::max_digit_value;
+
+ static int_type epsilon () throw() { return int_type(0U); }
+ static int_type round_error() throw() { return int_type(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 int_type infinity () throw() { return int_type(0U); }
+ static int_type quiet_NaN () throw() { return int_type(0U); }
+ static int_type signaling_NaN() throw() { return int_type(0U); }
+ static int_type denorm_min () throw() { return int_type(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;
+};
+
+
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::is_specialized;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::digits;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::digits10;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::is_signed;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::is_integer;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::is_exact;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::radix;
+template<bool S, class A, class T>
+const typename boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> >::digit_type
+numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::max_radix_value;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::min_exponent;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::min_exponent10;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::max_exponent;
+template<bool S, class A, class T>
+const int numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::max_exponent10;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::has_infinity;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::has_quiet_NaN;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::has_signaling_NaN;
+template<bool S, class A, class T>
+const float_denorm_style numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::has_denorm;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::is_iec559;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::is_bounded;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::is_modulo;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::traps;
+template<bool S, class A, class T>
+const bool numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::tinyness_before;
+template<bool S, class A, class T>
+const float_round_style numeric_limits<boost::mp_math::integer<boost::mp_math::unbounded<S,A,T> > >::round_style;
+
 } // namespace std
 
+
+#endif
+

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/operators.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/operators.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,1019 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// 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.size() == rhs.size() &&
- 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)
-{
- 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;
-
- 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 character string
-template<class A, class T, typename charT>
-inline bool
-operator == (const mp_int<A,T>& lhs, const charT* rhs) { return lhs == mp_int<A,T>(rhs); }
-
-template<class A, class T, typename charT>
-inline bool
-operator != (const mp_int<A,T>& lhs, const charT* rhs) { return lhs != mp_int<A,T>(rhs); }
-
-template<class A, class T, typename charT>
-inline bool
-operator < (const mp_int<A,T>& lhs, const charT* rhs) { return lhs < mp_int<A,T>(rhs); }
-
-template<class A, class T, typename charT>
-inline bool
-operator > (const mp_int<A,T>& lhs, const charT* rhs) { return lhs > mp_int<A,T>(rhs); }
-
-template<class A, class T, typename charT>
-inline bool
-operator <= (const mp_int<A,T>& lhs, const charT* rhs) { return lhs <= mp_int<A,T>(rhs); }
-
-template<class A, class T, typename charT>
-inline bool
-operator >= (const mp_int<A,T>& lhs, const charT* rhs) { return lhs >= mp_int<A,T>(rhs); }
-
-// compare const charT* to mp_int
-template<class A, class T, typename charT>
-inline bool
-operator == (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) == rhs; }
-
-template<class A, class T, typename charT>
-inline bool
-operator != (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) != rhs; }
-
-template<class A, class T, typename charT>
-inline bool
-operator < (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) < rhs; }
-
-template<class A, class T, typename charT>
-inline bool
-operator > (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) > rhs; }
-
-template<class A, class T, typename charT>
-inline bool
-operator <= (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) <= rhs; }
-
-template<class A, class T, typename charT>
-inline bool
-operator >= (const charT* lhs, const mp_int<A,T>& rhs) { return mp_int<A,T>(lhs) >= rhs; }
-
-
-// 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(size_ + 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 < size_; ++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)
- push(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 (*this)
- set_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.size_);
- set_sign(rhs.sign());
- x = &rhs;
- y = this;
- }
-
- ops_type::sub_smaller_magnitude(digits_, x->digits_, x->size_,
- y->digits_, y->size_);
- size_ = x->size_;
-
- clamp();
-
- if (!*this)
- set_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.size_);
- // result has opposite sign from *this
- set_sign(is_positive() ? -1 : 1);
- x = &rhs;
- y = this;
- }
-
- ops_type::sub_smaller_magnitude(digits_, x->digits_, x->size_,
- y->digits_, y->size_);
-
- size_ = x->size_;
-
- clamp();
-
- if (!*this)
- set_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(size_, rhs.size_);
-
- 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(size_ + rhs.size_);
-
- if (size_ == rhs.size_)
- ops_type::comba_mul(tmp.digits(), digits(), rhs.digits(), size_);
- else
- {
- // always multiply larger by smaller number
- const mp_int* a = this;
- const mp_int* b = &rhs;
- if (a->size_ < b->size_)
- std::swap(a, b);
-
- ops_type::comba_mul(tmp.digits(), a->digits(), a->size_, b->digits(), b->size_);
- }
-
- tmp.size_ = size_ + rhs.size_;
- tmp.clamp();
- *this = tmp;
- }
-
- set_sign(!*this ? 1 : neg);
-
- return *this;
-}
-
-template<class A, class T>
-mp_int<A,T>& mp_int<A,T>::operator /= (const mp_int<A,T>& rhs)
-{
- const mp_int<A,T> tmp(*this);
- detail::classic_divide(tmp, rhs, *this);
- 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> quotient;
- detail::classic_divide(*this, rhs, quotient, this);
- 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 (size_ > rhs.size_)
- {
- tmp = *this;
- px = rhs.size_;
- x = &rhs;
- }
- else
- {
- tmp = rhs;
- px = size_;
- 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 (size_ > rhs.size_)
- {
- tmp = *this;
- px = rhs.size_;
- x = &rhs;
- }
- else
- {
- tmp = rhs;
- px = size_;
- 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.size_ - 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 (size_ > rhs.size_)
- {
- tmp = *this;
- px = rhs.size_;
- x = &rhs;
- }
- else
- {
- tmp = rhs;
- px = size_;
- 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 character strings
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator += (const charT* s) { return *this += mp_int<A,T>(s); }
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator -= (const charT* s) { return *this -= mp_int<A,T>(s); }
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator *= (const charT* s) { return *this *= mp_int<A,T>(s); }
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator /= (const charT* s) { return *this /= mp_int<A,T>(s); }
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator %= (const charT* s) { return *this %= mp_int<A,T>(s); }
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator |= (const charT* s) { return *this |= mp_int<A,T>(s); }
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator &= (const charT* s) { return *this &= mp_int<A,T>(s); }
-template<class A, class T>
-template<typename charT>
-inline mp_int<A,T>& mp_int<A,T>::operator ^= (const charT* s) { return *this ^= mp_int<A,T>(s); }
-
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator + (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv += mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator - (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv -= mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator * (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv *= mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator / (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv /= mp_int<A,T>(rhs);
- return nrv;
-}
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator % (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv %= mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator | (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv |= mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator & (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv &= mp_int<A,T>(rhs);
- return nrv;
-}
-
-template<class A, class T, typename charT>
-inline mp_int<A,T> operator ^ (const mp_int<A,T>& lhs, const charT* rhs)
-{
- mp_int<A,T> nrv(lhs);
- nrv ^= mp_int<A,T>(rhs);
- return nrv;
-}
-
-
-// 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());
-}
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/pow.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/pow.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,66 +0,0 @@
-// 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_capacity(b / digit_bits + 1);
-
- // set size_ to where the bit will go
- size_ = b / digit_bits + 1;
-
- // set all bits to zero
- std::memset(digits_, 0, size_ * sizeof(digit_type));
-
- // put the single bit in its place
- digits_[b / digit_bits] = digit_type(1) << (b % digit_bits);
-}
-
-// calculate c = x**y using a square-multiply algorithm
-template<class A, class T>
-mp_int<A,T> pow(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type y)
-{
- mp_int<A,T> result;
-
- result = typename mp_int<A,T>::digit_type(1);
-
- const typename mp_int<A,T>::digit_type mask = 1 << (mp_int<A,T>::digit_bits - 1);
-
- for (int i = 0; i < mp_int<A,T>::digit_bits; ++i)
- {
- result.sqr();
-
- // if the bit is set multiply
- if (y & mask)
- result *= x;
-
- // shift to next bit
- y <<= 1;
- }
-
- return result;
-}
-
-template<class A, class T>
-mp_int<A,T> pow(const mp_int<A,T>& x, const mp_int<A,T>& y)
-{
- if (y.size() == 1)
- return pow(x, y[0]);
-
- mp_int<A,T> y0(y);
-
- y0.divide_by_2();
-
- mp_int<A,T> y1(y0);
-
- if (y.is_odd())
- ++y1;
-
- return pow(x, y0) * pow(x, y1);
-}
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/root.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/root.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,204 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_MP_MATH_MP_INT_ROOT_HPP
-#define BOOST_MP_MATH_MP_INT_ROOT_HPP
-
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
-
-
-namespace boost {
-namespace mp_math {
-
-template<class A, class T>
-mp_int<A,T> sqrt(const mp_int<A,T>& x)
-{
- if (x.is_negative())
- throw std::domain_error("sqrt: argument must be positive");
-
- mp_int<A,T> t1;
-
- if (!x)
- {
- 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;
-}
-
-
-// Uses Newton-Raphson approximation.
-template<class A, class T>
-mp_int<A,T> nth_root(const mp_int<A,T>& x, typename mp_int<A,T>::digit_type n)
-{
- if ((n & 1) == 0 && x.is_negative())
- throw std::domain_error("nth_root: argument must be positive if n is even");
-
- if (n == 0U)
- throw std::domain_error("nth_root: n must not be zero");
- else if (n == 1U)
- return x;
-
- // if x is negative fudge the sign but keep track
- const int neg = x.sign();
- const_cast<mp_int<A,T>*>(&x)->set_sign(1);
-
- mp_int<A,T> t1, t2, t3;
-
- typedef typename mp_int<A,T>::size_type size_type;
-
- // initial approximation
- const size_type result_precision = (x.precision() - 1) / n + 1;
- t2.grow_capacity(1);
- t2.set_size(1);
- t2[0] = 0;
- t2.set_bits(0, result_precision + 1);
-
- do
- {
- t1 = t2;
-
- // t2 = t1 - ((t1**n - x) / (n * t1**(n-1)))
-
- // t3 = t1**(n-1)
- t3 = pow(t1, n-1);
-
- // 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;
- 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;
-}
-
-template<class A, class T>
-mp_int<A,T> nth_root(const mp_int<A,T>& x, const mp_int<A,T>& n)
-{
- if (n.is_odd() && x.is_negative())
- throw std::domain_error("nth_root: argument must be positive if n is even");
-
- if (n.size() == 1)
- return nth_root(x, n[0]);
-
- // if x is negative fudge the sign but keep track
- const int neg = x.sign();
- const_cast<mp_int<A,T>*>(&x)->set_sign(1);
-
- mp_int<A,T> t1, t2, t3;
-
- typedef typename mp_int<A,T>::size_type size_type;
-
- static const size_type digit_bits = mp_int<A,T>::digit_bits;
-
- const size_type result_precision = (x.precision() - 1)
- / n.template to_integral<size_type>() + 1;
-
- t2.grow_capacity((result_precision + digit_bits - 1) / digit_bits);
- t2.set_size ((result_precision + digit_bits - 1) / digit_bits);
-
- t2[t2.size()-1] = 0;
- t2.set_bits(0, result_precision + 1);
-
- do
- {
- t1 = t2;
-
- // t2 = t1 - ((t1**n - x) / (n * t1**(n-1)))
-
- // t3 = t1**(n-1)
- t3 = pow(t1, n-1);
-
- // numerator
- // t2 = t1**n
- t2 = t3 * t1;
-
- // t2 = t1**n - x
- t2 -= x;
-
- // denominator
- // t3 = t1**(n-1) * n
- t3 *= 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;
- 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;
-}
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/sqr.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,220 +0,0 @@
-// 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 = size_ / 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 = size_ >> 1;
-
- /* init copy all the temps */
- x0.grow_capacity(B);
- x1.grow_capacity(size_ - B);
-
- /* init temps */
- x0x0.grow_capacity(B * 2);
- x1x1.grow_capacity((size_ - B) * 2);
-
- /* now shift the digits */
- std::memcpy(x0.digits_, digits_, B * sizeof(digit_type));
- std::memcpy(x1.digits_, digits_ + B, (size_ - B) * sizeof(digit_type));
-
- x0.size_ = B;
- x1.size_ = size_ - 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()
-{
- if (size() < 16U)
- {
- grow_capacity(size() + size());
-
- digit_type Z[32];
-
- ops_type::comba_sqr(Z, digits(), size());
-
- std::memcpy(digits(), Z, (size() + size()) * sizeof(digit_type));
-
- set_size(size() + size());
-
- if (!digits()[size()-1])
- pop();
- }
- else
- {
- mp_int tmp;
- tmp.grow_capacity(size() + size());
-
- ops_type::comba_sqr(tmp.digits(), digits(), size());
-
- tmp.set_size(size() + size());
-
- if (!tmp[tmp.size()-1])
- tmp.pop();
-
- *this = tmp;
- }
-}
-
-// computes *this = *this * *this
-template<class A, class T>
-void mp_int<A,T>::sqr()
-{
- if (size_ >= traits_type::toom_sqr_cutoff)
- toom_sqr();
- else if (size_ >= traits_type::karatsuba_sqr_cutoff)
- karatsuba_sqr();
- else
- comba_sqr();
- set_sign(1);
-}
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/string_conversion.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,314 +0,0 @@
-// 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:
-// - size_ = 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(size_ == 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)
- {
- push(result);
- offset -= valid_bits;
- result = static_cast<digit_type>(x >> (sc.radix_storage_bits - offset));
- }
- }
-
- if (result || is_uninitialized())
- push(result);
-
- clamp();
-
- if (!*this)
- set_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 (size_)
- {
- digit_type carry = ops_type::multiply_by_digit(digits_, digits_, size_,
- sc.max_power_value);
-
- carry += ops_type::add_single_digit(digits_, digits_, size_, result);
-
- if (carry)
- push(carry);
- }
- else
- push(result);
- }
-
- // one last round for the remaining decimal digits
- if (first != last)
- {
- digit_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 (size_)
- {
- digit_type carry = ops_type::multiply_by_digit(digits_, digits_, size_,
- static_cast<digit_type>(radix_power));
-
- carry += ops_type::add_single_digit(digits_, digits_, size_, result);
-
- if (carry)
- push(carry);
- }
- else
- push(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 (is_uninitialized())
- 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 (!*this)
- {
- 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 = (digit_type(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)
- {
- digit_type remainder = ops_type::divide_by_digit(tmp.digits(),
- tmp.digits(),
- tmp.size(),
- sc.max_power_value);
- tmp.clamp_high_digit();
-
- for (digit_type i = 0; i < m; ++i)
- {
- if (remainder || tmp)
- *c++ = static_cast<char_type>('0' + remainder % 10U);
- remainder /= 10U;
- }
- }
- std::reverse(sd.ptr + prefix_offset, c);
- }
-
- s.assign(sd.ptr, c);
-
- return s;
-}
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/sub.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/sub.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,44 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-template<class A, class T>
-void mp_int<A,T>::sub_digit(digit_type b)
-{
- if (is_negative())
- {
- const digit_type carry =
- ops_type::add_single_digit(digits_, digits_, size_, b);
- if (carry)
- push(carry);
- return;
- }
-
- if (size_ == 1)
- {
- if (digits_[0] < b) // example: 2 - 6 = -4
- {
- digits_[0] = b - digits_[0];
- set_sign(-1);
- }
- else // example: 8 - 7 = 1 or 5 - 5 = 0
- digits_[0] -= b;
- }
- else
- {
- ops_type::subtract_single_digit(digits_, digits_, size_, b);
- if (!digits_[size_-1])
- --size_;
- }
-}
-
-// 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_, size_, rhs.digits_, rhs.size_);
-
- clamp();
-}
-

Deleted: /sandbox/mp_math/boost/mp_math/mp_int/traits.hpp
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/traits.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,99 +0,0 @@
-// 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 <limits>
-#include <boost/config.hpp>
-#include <boost/static_assert.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 Digit digit_type;
- typedef Word word_type;
-
- static std::size_t toom_mul_cutoff;
- static std::size_t toom_sqr_cutoff;
- static std::size_t karatsuba_mul_cutoff;
- static std::size_t karatsuba_sqr_cutoff;
-};
-
-
-#define BMPINT_init(S) template<typename D, typename W>\
- S mp_int_traits<D,W>::
-BMPINT_init(std::size_t)toom_mul_cutoff = 350;
-BMPINT_init(std::size_t)toom_sqr_cutoff = 400;
-BMPINT_init(std::size_t)karatsuba_mul_cutoff = 80;
-BMPINT_init(std::size_t)karatsuba_sqr_cutoff = 120;
-
-#undef BMPINT_init
-
-
-
-} // namespace mp_math
-} // namespace boost
-
-#endif
-

Added: sandbox/mp_math/boost/mp_math/integer/unbounded.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/unbounded.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,118 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_UNBOUNDED_HPP
+#define BOOST_MP_MATH_INTEGER_UNBOUNDED_HPP
+
+#include <boost/config.hpp>
+#include <boost/mp_math/integer/unbounded_int.hpp>
+#include <boost/mp_math/integer/unbounded_uint.hpp>
+#include <boost/mp_math/integer/unbounded_traits.hpp>
+
+namespace boost {
+namespace mp_math {
+
+template<
+ bool IsSigned = true,
+ class Alloc = std::allocator<void>,
+ class Traits = unbounded_traits<>
+>
+struct unbounded
+:
+ mpl::if_c<
+ IsSigned,
+ unbounded_int<Alloc,Traits>,
+ unbounded_uint<Alloc,Traits>
+ >::type
+{
+ typedef typename mpl::if_c<
+ IsSigned,
+ unbounded_int<Alloc,Traits>,
+ unbounded_uint<Alloc,Traits>
+ >::type base_type;
+
+ // these constants are used by the numeric_limits specialization
+ static const bool is_signed = IsSigned;
+ static const bool is_bounded = false;
+
+ typedef typename base_type::traits_type traits_type;
+ typedef typename base_type::digit_type digit_type;
+ typedef typename base_type::size_type size_type;
+
+ unbounded(){}
+
+ #if !defined(BOOST_NO_VARIADIC_TEMPLATES) &&\
+ !defined(BOOST_NO_RVALUE_REFERENCES)
+ template<typename... Args>
+ unbounded(Args&&... args)
+ :
+ base_type(args...)
+ {}
+
+ #else
+
+ template<typename T1>
+ unbounded(const T1& t1)
+ : base_type(t1) {}
+
+ template<typename T1, typename T2>
+ unbounded(const T1& t1, const T2& t2)
+ : base_type(t1, t2) {}
+
+ template<typename T1, typename T2, typename T3>
+ unbounded(const T1& t1, const T2& t2, const T3& t3)
+ : base_type(t1, t2, t3) {}
+
+ template<typename T1, typename T2, typename T3, typename T4>
+ unbounded(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
+ : base_type(t1, t2, t3, t4) {}
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ unbounded(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5)
+ : base_type(t1, t2, t3, t4, t5) {}
+ #endif
+
+ template<typename T>
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ unbounded& operator = (T&& t)
+ #else
+ unbounded& operator = (const T& t)
+ #endif
+ {
+ base_type::operator=(t);
+ return *this;
+ }
+
+ operator base_type& () { return *this; }
+ operator const base_type& () const { return *this; }
+};
+
+
+template<bool S, class A, class T>
+struct modpow_ctx<unbounded<S,A,T> >
+:
+ modpow_ctx<typename unbounded<S,A,T>::base_type>
+{};
+
+// returns base^exp % mod
+template<bool S, class A, class T>
+inline
+unbounded<S,A,T> modpow(const unbounded<S,A,T>& base,
+ const unbounded<S,A,T>& exp,
+ const unbounded<S,A,T>& mod,
+ modpow_ctx<unbounded<S,A,T> >* ctx = 0)
+{
+ return modpow(static_cast<const typename unbounded<S,A,T>::base_type&>(base),
+ static_cast<const typename unbounded<S,A,T>::base_type&>(exp),
+ static_cast<const typename unbounded<S,A,T>::base_type&>(mod),
+ static_cast<modpow_ctx<typename unbounded<S,A,T>::base_type>*>(ctx));
+}
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/unbounded_int.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/unbounded_int.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,1469 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_UNBOUNDED_INT_HPP
+#define BOOST_MP_MATH_INTEGER_UNBOUNDED_INT_HPP
+
+#include <boost/config.hpp>
+#include <boost/mp_math/integer/contexts.hpp>
+#include <boost/mp_math/integer/unbounded_traits.hpp>
+#include <boost/mp_math/integer/detail/adder.hpp>
+#include <boost/mp_math/integer/detail/bitwise_ops.hpp>
+#include <boost/mp_math/integer/detail/divider.hpp>
+#include <boost/mp_math/integer/detail/gcd.hpp>
+#include <boost/mp_math/integer/detail/jacobi.hpp>
+#include <boost/mp_math/integer/detail/lcm.hpp>
+#include <boost/mp_math/integer/detail/modinv.hpp>
+#include <boost/mp_math/integer/detail/modpow.hpp>
+#include <boost/mp_math/integer/detail/power.hpp>
+#include <boost/mp_math/integer/detail/root.hpp>
+#include <boost/mp_math/integer/detail/string_conversion.hpp>
+#include <boost/mp_math/integer/detail/unbounded_int_integral.hpp>
+#include <boost/mp_math/integer/detail/base/unbounded_int.hpp>
+
+namespace boost {
+namespace mp_math {
+
+template<
+ class Alloc = std::allocator<void>,
+ class Traits = unbounded_traits<>
+>
+struct unbounded_int
+:
+ /*typename*/ Alloc::template rebind<typename Traits::digit_type>::other,
+ detail::base::unbounded_int<Traits>
+{
+protected:
+
+ typedef detail::base::unbounded_int<Traits> base_type;
+
+ typedef typename Alloc::template
+ rebind<typename Traits::digit_type>::other base_allocator_type;
+
+public:
+
+ template<typename IntegralT>
+ struct integral_ops
+ :
+ detail::unbounded_int_integral_ops<unbounded_int, IntegralT>
+ {};
+
+ typedef Alloc allocator_type;
+ typedef Traits traits_type;
+ typedef typename traits_type::digit_type digit_type;
+ typedef typename allocator_type::size_type size_type;
+
+ typedef typename base_type::iterator iterator;
+ typedef typename base_type::const_iterator const_iterator;
+ typedef typename base_type::reverse_iterator reverse_iterator;
+ typedef typename base_type::const_reverse_iterator const_reverse_iterator;
+ typedef typename base_type::magnitude_type magnitude_type;
+
+ unbounded_int();
+
+ explicit unbounded_int(const allocator_type& a);
+
+ template<typename IntegralT>
+ unbounded_int(IntegralT,
+ const allocator_type& a = allocator_type(),
+ typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
+
+ template<typename charT>
+ unbounded_int(const charT*, const allocator_type& a = allocator_type());
+
+ template<typename charT>
+ unbounded_int(const charT*,
+ std::ios_base::fmtflags,
+ const allocator_type& a = allocator_type());
+
+ template<typename charT, class traits, class alloc>
+ unbounded_int(const std::basic_string<charT,traits,alloc>&,
+ const allocator_type& a = allocator_type());
+
+ template<typename charT, class traits, class alloc>
+ unbounded_int(const std::basic_string<charT,traits,alloc>&,
+ std::ios_base::fmtflags,
+ const allocator_type& a = allocator_type());
+
+ template<typename RandomAccessIterator>
+ unbounded_int(RandomAccessIterator first,
+ RandomAccessIterator last,
+ const allocator_type& a = allocator_type());
+
+ template<typename RandomAccessIterator>
+ unbounded_int(RandomAccessIterator first,
+ RandomAccessIterator last,
+ std::ios_base::fmtflags f,
+ const allocator_type& a = allocator_type());
+
+ unbounded_int(const unbounded_int& copy);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ unbounded_int(unbounded_int&& copy);
+ #endif
+
+ ~unbounded_int();
+
+ unbounded_int& operator = (const unbounded_int& rhs);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ unbounded_int& operator = (unbounded_int&& rhs);
+ #endif
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator = (IntegralT rhs);
+
+ template<typename charT>
+ unbounded_int& operator = (const charT*);
+
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator = (const std::basic_string<charT,traits,alloc>&);
+
+ template<typename charT>
+ void assign(const charT*, std::ios_base::fmtflags);
+
+ 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);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ void swap(unbounded_int&& other)
+ #else
+ void swap(unbounded_int& other)
+ #endif
+ {
+ base_type::swap(other);
+ }
+
+ allocator_type get_allocator() const { return allocator_type(); }
+
+ void reserve(size_type n);
+
+ unbounded_int& operator ++();
+ unbounded_int& operator --();
+ unbounded_int operator ++(int);
+ unbounded_int operator --(int);
+ unbounded_int& operator <<= (size_type);
+ unbounded_int& operator >>= (size_type);
+ unbounded_int& operator - ();
+
+ unbounded_int& operator += (const unbounded_int&);
+ unbounded_int& operator -= (const unbounded_int&);
+ unbounded_int& operator *= (const unbounded_int&);
+ unbounded_int& operator /= (const unbounded_int&);
+ unbounded_int& operator %= (const unbounded_int&);
+ unbounded_int& operator |= (const unbounded_int&);
+ unbounded_int& operator &= (const unbounded_int&);
+ unbounded_int& operator ^= (const unbounded_int&);
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator += (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator -= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator *= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator /= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator %= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator |= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator &= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_int&>::type
+ operator ^= (IntegralT);
+
+ template<typename charT> unbounded_int& operator += (const charT*);
+ template<typename charT> unbounded_int& operator -= (const charT*);
+ template<typename charT> unbounded_int& operator *= (const charT*);
+ template<typename charT> unbounded_int& operator /= (const charT*);
+ template<typename charT> unbounded_int& operator %= (const charT*);
+ template<typename charT> unbounded_int& operator |= (const charT*);
+ template<typename charT> unbounded_int& operator &= (const charT*);
+ template<typename charT> unbounded_int& operator ^= (const charT*);
+
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator += (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator -= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator *= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator /= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator %= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator |= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator &= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_int& operator ^= (const std::basic_string<charT,traits,alloc>&);
+
+ template<class StringT>
+ StringT to_string(std::ios_base::fmtflags f = std::ios_base::dec) const
+ {
+ StringT tmp;
+ detail::to_string_converter<unbounded_int> conv;
+ conv.convert(tmp, *this, f);
+ return tmp;
+ }
+
+protected:
+
+ template<typename Iter>
+ void init_from_string(Iter first, Iter last)
+ {
+ detail::from_string_converter<unbounded_int> conv;
+ conv.detect_properties(first, last);
+ conv.convert(*this, first, last);
+ if (*this)
+ base_type::set_sign_bit(conv.is_positive ? 0 : 1);
+ }
+
+ template<typename Iter>
+ void init_from_string(Iter first, Iter last, std::ios_base::fmtflags f)
+ {
+ detail::from_string_converter<unbounded_int> conv;
+ conv.detect_properties(first, last, f);
+ conv.convert(*this, first, last);
+ if (*this)
+ base_type::set_sign_bit(conv.is_positive ? 0 : 1);
+ }
+};
+
+
+template<class A, class T>
+inline void swap(unbounded_int<A,T>& lhs, unbounded_int<A,T>& rhs)
+{
+ lhs.swap(rhs);
+}
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class A, class T>
+inline void swap(unbounded_int<A,T>&& lhs, unbounded_int<A,T>& rhs)
+{
+ lhs.swap(rhs);
+}
+template<class A, class T>
+inline void swap(unbounded_int<A,T>& lhs, unbounded_int<A,T>&& rhs)
+{
+ lhs.swap(rhs);
+}
+#endif
+
+
+template<class A, class T>
+unbounded_int<A,T>::unbounded_int()
+:
+ base_type(0, 0, 0)
+{
+}
+
+template<class A, class T>
+unbounded_int<A,T>::unbounded_int(const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+}
+
+template<class A, class T>
+template<typename IntegralT>
+unbounded_int<A,T>::unbounded_int(
+ IntegralT b,
+ const allocator_type& a,
+ typename enable_if<is_integral<IntegralT> >::type*)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ integral_ops<IntegralT>::assign(*this, b);
+}
+
+template<class A, class T>
+template<typename RandomAccessIterator>
+unbounded_int<A,T>::unbounded_int(RandomAccessIterator first,
+ RandomAccessIterator last,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(first, last);
+}
+
+template<class A, class T>
+template<typename charT>
+unbounded_int<A,T>::unbounded_int(const charT* s, const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s, s + std::char_traits<charT>::length(s));
+}
+
+template<class A, class T>
+template<typename charT>
+unbounded_int<A,T>::unbounded_int(const charT* s,
+ std::ios_base::fmtflags f,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s, s + std::char_traits<charT>::length(s), f);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+unbounded_int<A,T>::unbounded_int(
+ const std::basic_string<charT,traits,Alloc>& s,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s.begin(), s.end());
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+unbounded_int<A,T>::unbounded_int(
+ const std::basic_string<charT,traits,Alloc>& s,
+ std::ios_base::fmtflags f,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s.begin(), s.end(), f);
+}
+
+
+template<class A, class T>
+unbounded_int<A,T>::unbounded_int(const unbounded_int& copy)
+:
+ base_allocator_type(copy.get_allocator())
+{
+ base_type::digits_ = this->allocate(copy.size());
+ std::memcpy(base_type::digits_,
+ copy.digits(), copy.size() * sizeof(digit_type));
+ base_type::set_size(copy.size());
+ base_type::set_capacity(copy.size());
+ base_type::set_sign_bit(copy.sign_bit());
+}
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class A, class T>
+unbounded_int<A,T>::unbounded_int(unbounded_int&& copy)
+:
+ base_type(copy.digits(), copy.size(), copy.capacity_)
+{
+ copy.digits_ = 0;
+ copy.size_ = 0;
+ copy.capacity_ = 0;
+}
+#endif
+
+
+template<class A, class T>
+unbounded_int<A,T>::~unbounded_int()
+{
+ base_type::assert_invariants();
+ if (base_type::digits())
+ this->deallocate(base_type::digits(), base_type::capacity());
+}
+
+template<class A, class T>
+unbounded_int<A,T>&
+unbounded_int<A,T>::operator = (const unbounded_int<A,T>& rhs)
+{
+ if (this != &rhs)
+ {
+ if ((base_type::capacity() == 0) || (base_type::capacity() < rhs.size()))
+ unbounded_int(rhs).swap(*this);
+ else
+ {
+ std::memcpy(base_type::digits_,
+ rhs.digits(), rhs.size() * sizeof(digit_type));
+ base_type::set_size(rhs.size());
+ base_type::set_sign_bit(rhs.sign_bit());
+ }
+ }
+ return *this;
+}
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class A, class T>
+unbounded_int<A,T>& unbounded_int<A,T>::operator = (unbounded_int<A,T>&& rhs)
+{
+ if (this != &rhs)
+ {
+ if (base_type::digits())
+ this->deallocate(base_type::digits(), base_type::capacity());
+ base_type::digits_ = 0;
+ base_type::size_ = 0;
+ base_type::capacity_ = 0;
+ swap(rhs);
+ }
+ return *this;
+}
+#endif
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator = (IntegralT rhs)
+{
+ integral_ops<IntegralT>::assign(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename charT>
+unbounded_int<A,T>& unbounded_int<A,T>::operator = (const charT* s)
+{
+ base_type::set_size(0);
+ init_from_string(s, s + std::char_traits<charT>::length(s));
+ if (!*this) // This may happen on the input "0"
+ base_type::set_sign(1);
+ return *this;
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+unbounded_int<A,T>&
+unbounded_int<A,T>::operator = (const std::basic_string<charT,traits,Alloc>& s)
+{
+ base_type::set_size(0);
+ init_from_string(s.begin(), s.end());
+ if (!*this)
+ base_type::set_sign(1);
+ return *this;
+}
+
+template<class A, class T>
+template<typename charT>
+inline void
+unbounded_int<A,T>::assign(const charT* s, std::ios_base::fmtflags f)
+{
+ assign(s, s + std::char_traits<charT>::length(s), f);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline void
+unbounded_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
+unbounded_int<A,T>::assign(RandomAccessIterator first,
+ RandomAccessIterator last,
+ std::ios_base::fmtflags f)
+{
+ base_type::set_size(0);
+ init_from_string(first, last, f);
+ if (!*this)
+ base_type::set_sign(1);
+}
+
+template<class A, class T>
+void unbounded_int<A,T>::reserve(size_type n)
+{
+ if (base_type::capacity() < n)
+ {
+ const size_type new_cap = base_type::capacity() + base_type::capacity();
+ if (new_cap > n)
+ n = new_cap;
+ digit_type* d = this->allocate(n, base_type::digits_);
+ std::memcpy(d, base_type::digits(), sizeof(digit_type) * base_type::size());
+ this->deallocate(base_type::digits_, base_type::capacity());
+ base_type::digits_ = d;
+ base_type::set_capacity(n);
+ }
+}
+
+// prefix ops
+template<class A, class T>
+inline unbounded_int<A,T>& unbounded_int<A,T>::operator ++()
+{
+ reserve(base_type::size() + 1);
+ base_type::operator++();
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>& unbounded_int<A,T>::operator --()
+{
+ base_type::operator--();
+ return *this;
+}
+
+// postfix ops
+template<class A, class T>
+inline unbounded_int<A,T> unbounded_int<A,T>::operator ++(int)
+{
+ unbounded_int<A,T> tmp(*this);
+ ++(*this);
+ return tmp;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> unbounded_int<A,T>::operator --(int)
+{
+ unbounded_int<A,T> tmp(*this);
+ --(*this);
+ return tmp;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>& unbounded_int<A,T>::operator <<= (size_type n)
+{
+ if (*this != digit_type(0))
+ detail::shifter<unbounded_int>::shift_bits_left(*this, n);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>& unbounded_int<A,T>::operator >>= (size_type n)
+{
+ detail::shifter<unbounded_int>::shift_bits_right(*this, n);
+ if (!*this)
+ base_type::set_sign_bit(0);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>
+operator << (const unbounded_int<A,T>& x,
+ typename unbounded_int<A,T>::size_type n)
+{
+ unbounded_int<A,T> nrv(x);
+ nrv <<= n;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>
+operator >> (const unbounded_int<A,T>& x,
+ typename unbounded_int<A,T>::size_type n)
+{
+ unbounded_int<A,T> nrv(x);
+ nrv >>= n;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>&
+unbounded_int<A,T>::operator += (const unbounded_int<A,T>& rhs)
+{
+ detail::adder<unbounded_int, true>::add(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>&
+unbounded_int<A,T>::operator -= (const unbounded_int<A,T>& rhs)
+{
+ detail::adder<unbounded_int, true>::subtract(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>&
+unbounded_int<A,T>::operator *= (const unbounded_int<A,T>& rhs)
+{
+ detail::multiplier<unbounded_int>::multiply_or_square(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+unbounded_int<A,T>&
+unbounded_int<A,T>::operator /= (const unbounded_int<A,T>& rhs)
+{
+ const unbounded_int tmp(*this);
+ detail::divider<unbounded_int>::classic_divide(tmp, rhs, *this);
+ base_type::set_sign_bit(tmp.sign_bit() ^ rhs.sign_bit());
+ return *this;
+}
+
+template<class A, class T>
+unbounded_int<A,T>&
+unbounded_int<A,T>::operator %= (const unbounded_int<A,T>& rhs)
+{
+ const bool sign = base_type::sign_bit();
+ unbounded_int quotient;
+ detail::divider<unbounded_int>::classic_divide(*this, rhs, quotient, this);
+ if (*this)
+ base_type::set_sign_bit(sign);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>&
+unbounded_int<A,T>::operator |= (const unbounded_int<A,T>& rhs)
+{
+ detail::bitwise_ops<unbounded_int>::or_bits(*this, *this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>&
+unbounded_int<A,T>::operator &= (const unbounded_int<A,T>& rhs)
+{
+ detail::bitwise_ops<unbounded_int>::and_bits(*this, *this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T>&
+unbounded_int<A,T>::operator ^= (const unbounded_int<A,T>& rhs)
+{
+ detail::bitwise_ops<unbounded_int>::xor_bits(*this, *this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator + (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv += rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator - (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv -= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator * (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv;
+ detail::multiplier<unbounded_int<A,T> >::multiply_or_square(nrv, lhs, rhs);
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator / (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv /= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator % (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv %= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator | (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv |= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator & (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv &= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_int<A,T> operator ^ (const unbounded_int<A,T>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv ^= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+unbounded_int<A,T> operator ~ (const unbounded_int<A,T>& x)
+{
+ unbounded_int<A,T> nrv;
+ nrv.reserve(x.size());
+ detail::base::bitwise_ops<unbounded_int<A,T> >::compl_bits(nrv, x);
+ return nrv;
+}
+
+// Arithmetic and bitwise operators involving integral types
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator += (IntegralT rhs)
+{
+ integral_ops<IntegralT>::add(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator -= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::subtract(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator *= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::multiply(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator /= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::divide(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator %= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::modulo(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator |= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_or(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator &= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_and(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T>&>::type
+unbounded_int<A,T>::operator ^= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_xor(*this, rhs);
+ return *this;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator + (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv += rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator - (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv -= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator * (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv *= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator / (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv /= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator % (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv %= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator | (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv |= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator & (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv &= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_int<A,T> >::type
+operator ^ (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_int<A,T> nrv(lhs);
+ nrv ^= rhs;
+ return nrv;
+}
+
+// compare unbounded_int to unbounded_int
+template<class A, class T>
+inline bool
+operator == (const unbounded_int<A,T>& lhs, const unbounded_int<A,T>& rhs)
+{
+ return (lhs.sign_bit() == rhs.sign_bit()) &&
+ (lhs.size() == rhs.size() ) &&
+ std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template<class A, class T>
+inline bool
+operator != (const unbounded_int<A,T>& lhs, const unbounded_int<A,T>& rhs)
+{
+ return !(lhs == rhs);
+}
+
+template<class A, class T>
+bool
+operator < (const unbounded_int<A,T>& lhs, const unbounded_int<A,T>& rhs)
+{
+ if (lhs.sign_bit() != rhs.sign_bit())
+ {
+ if (lhs.is_negative())
+ return true;
+ else
+ return false;
+ }
+
+ if (lhs.size() < rhs.size())
+ return true;
+ if (lhs.size() > rhs.size())
+ return false;
+
+ 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 unbounded_int<A,T>& lhs, const unbounded_int<A,T>& rhs)
+{
+ return rhs < lhs;
+}
+
+template<class A, class T>
+inline bool
+operator <= (const unbounded_int<A,T>& lhs, const unbounded_int<A,T>& rhs)
+{
+ return !(rhs < lhs);
+}
+
+template<class A, class T>
+inline bool
+operator >= (const unbounded_int<A,T>& lhs, const unbounded_int<A,T>& rhs)
+{
+ return !(lhs < rhs);
+}
+
+// compare unbounded_int to integral
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (const unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_int_integral_ops<
+ unbounded_int<A,T>, IntegralT>::equal(lhs, rhs);
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (const unbounded_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 unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_int_integral_ops<
+ unbounded_int<A,T>, IntegralT>::less(lhs, rhs);
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (const unbounded_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 unbounded_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 unbounded_int<A,T>& lhs, IntegralT rhs)
+{
+ return !(lhs < rhs);
+}
+
+// compare integral to unbounded_int
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (IntegralT lhs, const unbounded_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 unbounded_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 unbounded_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 unbounded_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 unbounded_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 unbounded_int<A,T>& rhs)
+{
+ return rhs <= lhs;
+}
+
+// compare unbounded_int to const charT*
+template<class A, class T, typename charT>
+inline bool
+operator == (const unbounded_int<A,T>& lhs, const charT* rhs)
+{
+ return lhs == unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator != (const unbounded_int<A,T>& lhs, const charT* rhs)
+{
+ return lhs != unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator < (const unbounded_int<A,T>& lhs, const charT* rhs)
+{
+ return lhs < unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator > (const unbounded_int<A,T>& lhs, const charT* rhs)
+{
+ return lhs > unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator <= (const unbounded_int<A,T>& lhs, const charT* rhs)
+{
+ return lhs <= unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator >= (const unbounded_int<A,T>& lhs, const charT* rhs)
+{
+ return lhs >= unbounded_int<A,T>(rhs);
+}
+
+// comparison const charT* to unbounded_int
+template<class A, class T, typename charT>
+inline bool
+operator == (const charT* lhs, const unbounded_int<A,T>& rhs)
+{
+ return unbounded_int<A,T>(lhs) == rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator != (const charT* lhs, const unbounded_int<A,T>& rhs)
+{
+ return unbounded_int<A,T>(lhs) != rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator < (const charT* lhs, const unbounded_int<A,T>& rhs)
+{
+ return unbounded_int<A,T>(lhs) < rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator > (const charT* lhs, const unbounded_int<A,T>& rhs)
+{
+ return unbounded_int<A,T>(lhs) > rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator <= (const charT* lhs, const unbounded_int<A,T>& rhs)
+{
+ return unbounded_int<A,T>(lhs) <= rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator >= (const charT* lhs, const unbounded_int<A,T>& rhs)
+{
+ return unbounded_int<A,T>(lhs) >= rhs;
+}
+
+// compare unbounded_int to basic_string
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator == (const unbounded_int<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs == unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator != (const unbounded_int<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs != unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator < (const unbounded_int<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs < unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator > (const unbounded_int<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs > unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const unbounded_int<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs <= unbounded_int<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const unbounded_int<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs >= unbounded_int<A,T>(rhs);
+}
+
+// compare basic_string to unbounded_int
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator == (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const unbounded_int<A,T>& rhs)
+{
+ return unbounded_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 unbounded_int<A,T>& rhs)
+{
+ return unbounded_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 unbounded_int<A,T>& rhs)
+{
+ return unbounded_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 unbounded_int<A,T>& rhs)
+{
+ return unbounded_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 unbounded_int<A,T>& rhs)
+{
+ return unbounded_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 unbounded_int<A,T>& rhs)
+{
+ return unbounded_int<A,T>(lhs) >= rhs;
+}
+
+// Input/Output
+template<class A, class T, typename charT, class traits>
+std::basic_istream<charT, traits>&
+operator >> (std::basic_istream<charT, traits>& is, unbounded_int<A,T>& x)
+{
+ typename std::basic_istream<charT, traits>::sentry sentry(is);
+ if (!sentry)
+ return is;
+
+ // TODO we read into a string first which costs memory and std::string
+ // allocator is not under user control. We should convert incoming digits
+ // directly. Actually we should check what is the fastest way.
+ 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 unbounded_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 unbounded_int<A,T>& x)
+{
+ // TODO same as above, we should output digits directly to the stream
+ return os << x.template to_string<std::string>(os.flags());
+}
+
+
+template<class A, class T>
+unbounded_int<A,T> abs(const unbounded_int<A,T>& x)
+{
+ unbounded_int<A,T> tmp(x);
+ tmp.set_sign_bit(0);
+ return tmp;
+}
+
+template<class A, class T>
+inline
+unbounded_int<A,T> gcd(const unbounded_int<A,T>& a,
+ const unbounded_int<A,T>& b)
+{
+ unbounded_int<A,T> z;
+ detail::gcd_finder<unbounded_int<A,T> >::gcd(z, a, b);
+ return z;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class A, class T, class... Integer>
+unbounded_int<A,T> gcd(const unbounded_int<A,T>& a,
+ const unbounded_int<A,T>& b,
+ const Integer&... args)
+{
+ return gcd(gcd(a, b), args...);
+}
+#endif
+
+template<class A, class T>
+inline
+unbounded_int<A,T> lcm(const unbounded_int<A,T>& a,
+ const unbounded_int<A,T>& b)
+{
+ unbounded_int<A,T> z;
+ detail::lcm_finder<unbounded_int<A,T> >::lcm(z, a, b);
+ return z;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class A, class T, class... Integer>
+unbounded_int<A,T> lcm(const unbounded_int<A,T>& a,
+ const unbounded_int<A,T>& b,
+ const Integer&... args)
+{
+ return lcm(lcm(a, b), args...);
+}
+#endif
+
+template<class A, class T>
+inline
+unbounded_int<A,T>
+pow(const unbounded_int<A,T>& x, typename unbounded_int<A,T>::size_type y)
+{
+ unbounded_int<A,T> z;
+ detail::power<unbounded_int<A,T> >::pow(z, x, y);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_int<A,T>
+pow(const unbounded_int<A,T>& x, const unbounded_int<A,T>& y)
+{
+ unbounded_int<A,T> z;
+ detail::power<unbounded_int<A,T> >::pow(z, x, y);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_int<A,T> sqrt(const unbounded_int<A,T>& x)
+{
+ unbounded_int<A,T> z;
+ detail::root<unbounded_int<A,T> >::sqrt(z, x);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_int<A,T> nth_root(typename unbounded_int<A,T>::size_type n,
+ const unbounded_int<A,T>& x)
+{
+ unbounded_int<A,T> z;
+ detail::root<unbounded_int<A,T> >::nth_root(z, n, x);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_int<A,T> nth_root(const unbounded_int<A,T>& n,
+ const unbounded_int<A,T>& x)
+{
+ unbounded_int<A,T> z;
+ detail::root<unbounded_int<A,T> >::nth_root(z, n, x);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_int<A,T> modinv(const unbounded_int<A,T>& x,
+ const unbounded_int<A,T>& m)
+{
+ unbounded_int<A,T> nrv;
+ detail::modular_inverter<unbounded_int<A,T> >::modinv(nrv, x, m);
+ return nrv;
+}
+
+template<class A, class T>
+struct modpow_ctx<unbounded_int<A,T> >
+:
+ detail::modpow_ctx<unbounded_int<A,T> >
+{};
+
+// returns base^exp % mod
+template<class A, class T>
+inline
+unbounded_int<A,T> modpow(const unbounded_int<A,T>& base,
+ const unbounded_int<A,T>& exp,
+ const unbounded_int<A,T>& mod,
+ modpow_ctx<unbounded_int<A,T> >* ctx = 0)
+{
+ unbounded_int<A,T> z;
+ detail::modular_power<unbounded_int<A,T> >::modpow(z, base, exp, mod, ctx);
+ return z;
+}
+
+template<class A, class T>
+inline
+int jacobi(const unbounded_int<A,T>& x, const unbounded_int<A,T>& y)
+{
+ return detail::jacobi(x, y);
+}
+
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif

Copied: sandbox/mp_math/boost/mp_math/integer/unbounded_traits.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int/traits.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int/traits.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/unbounded_traits.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,10 +1,10 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_MP_MATH_MP_INT_TRAITS_HPP
-#define BOOST_MP_MATH_MP_INT_TRAITS_HPP
+#ifndef BOOST_MP_MATH_INTEGER_UNBOUNDED_TRAITS_HPP
+#define BOOST_MP_MATH_INTEGER_UNBOUNDED_TRAITS_HPP
 
 #include <cstddef> // size_t
 #include <limits>
@@ -15,6 +15,7 @@
 #include <boost/mpl/deref.hpp>
 #include <boost/mpl/lower_bound.hpp>
 #include <boost/mpl/vector.hpp>
+#include <boost/mp_math/integer/detail/base/primitive_ops.hpp>
 
 
 namespace boost {
@@ -61,34 +62,56 @@
 
 
 template<
- typename Digit = detail::choose::digit_type,
- typename Word = detail::choose::word_type/*,
- bool debug = false*/
+ typename DigitT = detail::choose::digit_type,
+ typename WordT = detail::choose::word_type,
+ typename SizeT = std::size_t,
+ bool debug = false
>
-struct mp_int_traits
+struct unbounded_traits
 {
   BOOST_STATIC_ASSERT(
- std::numeric_limits<Digit>::digits <= std::numeric_limits<Word>::digits/2
+ std::numeric_limits<DigitT>::digits <= std::numeric_limits<WordT>::digits/2
   );
 
- typedef Digit digit_type;
- typedef Word word_type;
+ typedef DigitT digit_type;
+ typedef WordT word_type;
+ typedef SizeT size_type;
+
+#ifdef BOOST_MP_MATH_PRIMITIVE_OPS_OLD
+ typedef detail::base::primitive_ops<
+ digit_type, word_type, size_type> ops_type;
+#else
+ typedef detail::base::primitive_ops<digit_type, size_type> ops_type;
+#endif
 
- static std::size_t toom_mul_cutoff;
- static std::size_t toom_sqr_cutoff;
- static std::size_t karatsuba_mul_cutoff;
- static std::size_t karatsuba_sqr_cutoff;
-};
+ static const bool enable_debug_mode = debug;
 
+ static const size_type radix_bits = std::numeric_limits<digit_type>::digits;
+ static const size_type digit_bits = std::numeric_limits<digit_type>::digits;
+ static const digit_type max_digit_value = static_cast<digit_type>(-1);
+
+ static size_type toom_mul_threshold;
+ static size_type toom_sqr_threshold;
+ static size_type karatsuba_mul_threshold;
+ static size_type karatsuba_sqr_threshold;
+};
 
-#define BMPINT_init(S) template<typename D, typename W>\
- S mp_int_traits<D,W>::
-BMPINT_init(std::size_t)toom_mul_cutoff = 350;
-BMPINT_init(std::size_t)toom_sqr_cutoff = 400;
-BMPINT_init(std::size_t)karatsuba_mul_cutoff = 80;
-BMPINT_init(std::size_t)karatsuba_sqr_cutoff = 120;
 
-#undef BMPINT_init
+template<typename D, typename W, typename S, bool b>
+typename unbounded_traits<D,W,S,b>::size_type
+unbounded_traits<D,W,S,b>::toom_mul_threshold = 350;
+
+template<typename D, typename W, typename S, bool b>
+typename unbounded_traits<D,W,S,b>::size_type
+unbounded_traits<D,W,S,b>::toom_sqr_threshold = 400;
+
+template<typename D, typename W, typename S, bool b>
+typename unbounded_traits<D,W,S,b>::size_type
+unbounded_traits<D,W,S,b>::karatsuba_mul_threshold = 80;
+
+template<typename D, typename W, typename S, bool b>
+typename unbounded_traits<D,W,S,b>::size_type
+unbounded_traits<D,W,S,b>::karatsuba_sqr_threshold = 120;
 
 
 

Added: sandbox/mp_math/boost/mp_math/integer/unbounded_uint.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/unbounded_uint.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,1702 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_INTEGER_UNBOUNDED_UINT_HPP
+#define BOOST_MP_MATH_INTEGER_UNBOUNDED_UINT_HPP
+
+#include <boost/config.hpp>
+#include <boost/mp_math/integer/contexts.hpp>
+#include <boost/mp_math/integer/unbounded_traits.hpp>
+#include <boost/mp_math/integer/detail/adder.hpp>
+#include <boost/mp_math/integer/detail/bitwise_ops.hpp>
+#include <boost/mp_math/integer/detail/divider.hpp>
+#include <boost/mp_math/integer/detail/gcd.hpp>
+#include <boost/mp_math/integer/detail/jacobi.hpp>
+#include <boost/mp_math/integer/detail/lcm.hpp>
+#include <boost/mp_math/integer/detail/multiplier.hpp>
+#include <boost/mp_math/integer/detail/power.hpp>
+#include <boost/mp_math/integer/detail/root.hpp>
+#include <boost/mp_math/integer/detail/string_conversion.hpp>
+#include <boost/mp_math/integer/detail/unbounded_uint_integral.hpp>
+#include <boost/mp_math/integer/detail/base/unbounded_uint.hpp>
+
+namespace boost {
+namespace mp_math {
+
+template<
+ class Alloc = std::allocator<void>,
+ class Traits = unbounded_traits<>
+>
+struct unbounded_uint
+:
+ /*typename*/ Alloc::template rebind<typename Traits::digit_type>::other,
+ detail::base::unbounded_uint<Traits>
+{
+protected:
+
+ typedef detail::base::unbounded_uint<Traits> base_type;
+
+ typedef typename Alloc::template
+ rebind<typename Traits::digit_type>::other base_allocator_type;
+
+public:
+
+ template<typename IntegralT>
+ struct integral_ops
+ :
+ detail::unbounded_uint_integral_ops<unbounded_uint, IntegralT>
+ {};
+
+ typedef Alloc allocator_type;
+ typedef Traits traits_type;
+ typedef typename traits_type::digit_type digit_type;
+ typedef typename allocator_type::size_type size_type;
+
+ typedef typename base_type::iterator iterator;
+ typedef typename base_type::const_iterator const_iterator;
+ typedef typename base_type::reverse_iterator reverse_iterator;
+ typedef typename base_type::const_reverse_iterator const_reverse_iterator;
+
+ unbounded_uint();
+
+ explicit unbounded_uint(const allocator_type& a);
+
+ template<typename IntegralT>
+ unbounded_uint(IntegralT,
+ const allocator_type& a = allocator_type(),
+ typename enable_if<is_integral<IntegralT> >::type* dummy = 0);
+
+ template<typename charT>
+ unbounded_uint(const charT*, const allocator_type& a = allocator_type());
+
+ template<typename charT>
+ unbounded_uint(const charT*,
+ std::ios_base::fmtflags,
+ const allocator_type& a = allocator_type());
+
+ template<typename charT, class traits, class alloc>
+ unbounded_uint(const std::basic_string<charT,traits,alloc>&,
+ const allocator_type& a = allocator_type());
+
+ template<typename charT, class traits, class alloc>
+ unbounded_uint(const std::basic_string<charT,traits,alloc>&,
+ std::ios_base::fmtflags,
+ const allocator_type& a = allocator_type());
+
+ template<typename RandomAccessIterator>
+ unbounded_uint(RandomAccessIterator first,
+ RandomAccessIterator last,
+ const allocator_type& a = allocator_type());
+
+ template<typename RandomAccessIterator>
+ unbounded_uint(RandomAccessIterator first,
+ RandomAccessIterator last,
+ std::ios_base::fmtflags f,
+ const allocator_type& a = allocator_type());
+
+ unbounded_uint(const unbounded_uint& copy);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ unbounded_uint(unbounded_uint&& copy);
+ #endif
+
+ ~unbounded_uint();
+
+ unbounded_uint& operator = (const unbounded_uint& rhs);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ unbounded_uint& operator = (unbounded_uint&& rhs);
+ #endif
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator = (IntegralT rhs);
+
+ template<typename charT>
+ unbounded_uint& operator = (const charT*);
+
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator = (const std::basic_string<charT,traits,alloc>&);
+
+ template<typename charT>
+ void assign(const charT*, std::ios_base::fmtflags);
+
+ 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);
+
+ #ifndef BOOST_NO_RVALUE_REFERENCES
+ void swap(unbounded_uint&& other)
+ #else
+ void swap(unbounded_uint& other)
+ #endif
+ {
+ base_type::swap(other);
+ }
+
+ allocator_type get_allocator() const { return allocator_type(); }
+
+ void reserve(size_type n);
+
+ unbounded_uint& operator ++();
+ unbounded_uint& operator --();
+ unbounded_uint operator ++(int);
+ unbounded_uint operator --(int);
+ unbounded_uint& operator <<= (size_type);
+ unbounded_uint& operator >>= (size_type);
+
+ unbounded_uint& operator += (const unbounded_uint&);
+ unbounded_uint& operator -= (const unbounded_uint&);
+ unbounded_uint& operator *= (const unbounded_uint&);
+ unbounded_uint& operator /= (const unbounded_uint&);
+ unbounded_uint& operator %= (const unbounded_uint&);
+ unbounded_uint& operator |= (const unbounded_uint&);
+ unbounded_uint& operator &= (const unbounded_uint&);
+ unbounded_uint& operator ^= (const unbounded_uint&);
+
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator += (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator -= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator *= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator /= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator %= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator |= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator &= (IntegralT);
+ template<typename IntegralT>
+ typename enable_if<is_integral<IntegralT>, unbounded_uint&>::type
+ operator ^= (IntegralT);
+
+ template<typename charT> unbounded_uint& operator += (const charT*);
+ template<typename charT> unbounded_uint& operator -= (const charT*);
+ template<typename charT> unbounded_uint& operator *= (const charT*);
+ template<typename charT> unbounded_uint& operator /= (const charT*);
+ template<typename charT> unbounded_uint& operator %= (const charT*);
+ template<typename charT> unbounded_uint& operator |= (const charT*);
+ template<typename charT> unbounded_uint& operator &= (const charT*);
+ template<typename charT> unbounded_uint& operator ^= (const charT*);
+
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator += (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator -= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator *= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator /= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator %= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator |= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator &= (const std::basic_string<charT,traits,alloc>&);
+ template<typename charT, class traits, class alloc>
+ unbounded_uint& operator ^= (const std::basic_string<charT,traits,alloc>&);
+
+ template<class StringT>
+ StringT to_string(std::ios_base::fmtflags f = std::ios_base::dec) const
+ {
+ StringT tmp;
+ detail::to_string_converter<unbounded_uint> conv;
+ conv.convert(tmp, *this, f);
+ return tmp;
+ }
+
+protected:
+
+ template<typename Iter>
+ void init_from_string(Iter first, Iter last)
+ {
+ if (first < last)
+ {
+ detail::from_string_converter<unbounded_uint> conv;
+ conv.detect_properties(first, last);
+ if (!conv.is_positive)
+ throw std::invalid_argument("unbounded_uint::init_from_string: "
+ "cannot convert negative number to unsigned integer");
+ conv.convert(*this, first, last);
+ }
+ }
+
+ template<typename Iter>
+ void init_from_string(Iter first, Iter last, std::ios_base::fmtflags f)
+ {
+ if (first < last)
+ {
+ detail::from_string_converter<unbounded_uint> conv;
+ conv.detect_properties(first, last, f);
+ if (!conv.is_positive)
+ throw std::invalid_argument("unbounded_uint::init_from_string: "
+ "cannot convert negative number to unsigned integer");
+ conv.convert(*this, first, last);
+ }
+ }
+};
+
+
+template<class A, class T>
+unbounded_uint<A,T>::unbounded_uint()
+:
+ base_type(0, 0, 0)
+{
+}
+
+template<class A, class T>
+unbounded_uint<A,T>::unbounded_uint(const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+}
+
+template<class A, class T>
+template<typename IntegralT>
+unbounded_uint<A,T>::unbounded_uint(
+ IntegralT b,
+ const allocator_type& a,
+ typename enable_if<is_integral<IntegralT> >::type*)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ integral_ops<IntegralT>::assign(*this, b);
+}
+
+
+template<class A, class T>
+template<typename RandomAccessIterator>
+unbounded_uint<A,T>::unbounded_uint(RandomAccessIterator first,
+ RandomAccessIterator last,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(first, last);
+}
+
+template<class A, class T>
+template<typename charT>
+unbounded_uint<A,T>::unbounded_uint(const charT* s, const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s, s + std::char_traits<charT>::length(s));
+}
+
+template<class A, class T>
+template<typename charT>
+unbounded_uint<A,T>::unbounded_uint(const charT* s,
+ std::ios_base::fmtflags f,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s, s + std::char_traits<charT>::length(s), f);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+unbounded_uint<A,T>::unbounded_uint(
+ const std::basic_string<charT,traits,Alloc>& s,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s.begin(), s.end());
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+unbounded_uint<A,T>::unbounded_uint(
+ const std::basic_string<charT,traits,Alloc>& s,
+ std::ios_base::fmtflags f,
+ const allocator_type& a)
+:
+ base_allocator_type(a),
+ base_type(0, 0, 0)
+{
+ init_from_string(s.begin(), s.end(), f);
+}
+
+
+template<class A, class T>
+unbounded_uint<A,T>::unbounded_uint(const unbounded_uint& copy)
+:
+ base_allocator_type(copy.get_allocator())
+{
+ base_type::digits_ = this->allocate(copy.size());
+ std::memcpy(base_type::digits_,
+ copy.digits(), copy.size() * sizeof(digit_type));
+ base_type::set_size(copy.size());
+ base_type::set_capacity(copy.size());
+}
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class A, class T>
+unbounded_uint<A,T>::unbounded_uint(unbounded_uint&& copy)
+:
+ base_type(copy.digits(), copy.size(), copy.capacity())
+{
+ copy.digits_ = 0;
+ copy.size_ = 0;
+ copy.capacity_ = 0;
+}
+#endif
+
+
+template<class A, class T>
+unbounded_uint<A,T>::~unbounded_uint()
+{
+ base_type::assert_invariants();
+ if (base_type::digits())
+ this->deallocate(base_type::digits(), base_type::capacity());
+}
+
+template<class A, class T>
+unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator = (const unbounded_uint<A,T>& rhs)
+{
+ if (this != &rhs)
+ {
+ if ((base_type::capacity() == 0) || (base_type::capacity() < rhs.size()))
+ unbounded_uint(rhs).swap(*this);
+ else
+ {
+ std::memcpy(base_type::digits_,
+ rhs.digits(), rhs.size() * sizeof(digit_type));
+ base_type::set_size(rhs.size());
+ }
+ }
+ return *this;
+}
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+template<class A, class T>
+unbounded_uint<A,T>& unbounded_uint<A,T>::operator = (unbounded_uint<A,T>&& rhs)
+{
+ if (this != &rhs)
+ {
+ if (base_type::digits())
+ this->deallocate(base_type::digits(), base_type::capacity());
+ base_type::digits_ = 0;
+ base_type::size_ = 0;
+ base_type::capacity_ = 0;
+ swap(rhs);
+ }
+ return *this;
+}
+#endif
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator = (IntegralT rhs)
+{
+ integral_ops<IntegralT>::assign(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename charT>
+unbounded_uint<A,T>& unbounded_uint<A,T>::operator = (const charT* s)
+{
+ base_type::set_size(0);
+ init_from_string(s, s + std::char_traits<charT>::length(s));
+ return *this;
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator = (const std::basic_string<charT,traits,Alloc>& s)
+{
+ base_type::set_size(0);
+ init_from_string(s.begin(), s.end());
+ return *this;
+}
+
+template<class A, class T>
+template<typename charT>
+inline void
+unbounded_uint<A,T>::assign(const charT* s, std::ios_base::fmtflags f)
+{
+ assign(s, s + std::char_traits<charT>::length(s), f);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline void
+unbounded_uint<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
+unbounded_uint<A,T>::assign(RandomAccessIterator first,
+ RandomAccessIterator last,
+ std::ios_base::fmtflags f)
+{
+ base_type::set_size(0);
+ init_from_string(first, last, f);
+;
+}
+
+template<class A, class T>
+void unbounded_uint<A,T>::reserve(size_type n)
+{
+ if (base_type::capacity() < n)
+ {
+ const size_type new_cap = base_type::capacity() + base_type::capacity();
+ if (new_cap > n)
+ n = new_cap;
+ digit_type* d = this->allocate(n, base_type::digits_);
+ std::memcpy(d, base_type::digits(), sizeof(digit_type) * base_type::size());
+ this->deallocate(base_type::digits_, base_type::capacity());
+ base_type::digits_ = d;
+ base_type::set_capacity(n);
+ }
+}
+
+// prefix ops
+template<class A, class T>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator ++()
+{
+ reserve(base_type::size() + 1);
+ base_type::operator++();
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator --()
+{
+ base_type::operator--();
+ return *this;
+}
+
+// postfix ops
+template<class A, class T>
+inline unbounded_uint<A,T> unbounded_uint<A,T>::operator ++(int)
+{
+ unbounded_uint<A,T> tmp(*this);
+ ++(*this);
+ return tmp;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> unbounded_uint<A,T>::operator --(int)
+{
+ unbounded_uint<A,T> tmp(*this);
+ --(*this);
+ return tmp;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator <<= (size_type n)
+{
+ if (*this != digit_type(0))
+ detail::shifter<unbounded_uint>::shift_bits_left(*this, n);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator >>= (size_type n)
+{
+ detail::shifter<unbounded_uint>::shift_bits_right(*this, n);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>
+operator << (const unbounded_uint<A,T>& x,
+ typename unbounded_uint<A,T>::size_type n)
+{
+ unbounded_uint<A,T> nrv(x);
+ nrv <<= n;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>
+operator >> (const unbounded_uint<A,T>& x,
+ typename unbounded_uint<A,T>::size_type n)
+{
+ unbounded_uint<A,T> nrv(x);
+ nrv >>= n;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator += (const unbounded_uint<A,T>& rhs)
+{
+ detail::adder<unbounded_uint, false>::add(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator -= (const unbounded_uint<A,T>& rhs)
+{
+ detail::adder<unbounded_uint, false>::subtract(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator *= (const unbounded_uint<A,T>& rhs)
+{
+ detail::multiplier<unbounded_uint>::multiply_or_square(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator /= (const unbounded_uint<A,T>& rhs)
+{
+ const unbounded_uint tmp(*this);
+ detail::divider<unbounded_uint>::classic_divide(tmp, rhs, *this);
+ return *this;
+}
+
+template<class A, class T>
+unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator %= (const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint quotient;
+ detail::divider<unbounded_uint>::classic_divide(*this, rhs, quotient, this);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator |= (const unbounded_uint<A,T>& rhs)
+{
+ detail::bitwise_ops<unbounded_uint>::or_bits(*this, *this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator &= (const unbounded_uint<A,T>& rhs)
+{
+ detail::bitwise_ops<unbounded_uint>::and_bits(*this, *this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator ^= (const unbounded_uint<A,T>& rhs)
+{
+ detail::bitwise_ops<unbounded_uint>::xor_bits(*this, *this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> operator + (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv += rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> operator - (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv -= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> operator * (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv;
+ detail::multiplier<unbounded_uint<A,T> >::multiply_or_square(nrv, lhs, rhs);
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> operator / (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv /= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> operator % (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv %= rhs;
+ return nrv;
+}
+
+// TODO can do optimization here depending on which arg is larger, then
+// construct nrv from the larger to avoid a reallocation in op <<=. Same for
+// other args. The specific optimization that is possible depends on the
+// kind of operator we are looking at. That also means that we would need to
+// forward to these ops directly in integer.hpp. The same can be done for shift
+// operators << and >>.
+template<class A, class T>
+inline unbounded_uint<A,T> operator | (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv |= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> operator & (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv &= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+inline unbounded_uint<A,T> operator ^ (const unbounded_uint<A,T>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv ^= rhs;
+ return nrv;
+}
+
+template<class A, class T>
+unbounded_uint<A,T> operator ~ (const unbounded_uint<A,T>& x)
+{
+ unbounded_uint<A,T> nrv;
+ nrv.reserve(x.size());
+ detail::base::bitwise_ops<unbounded_uint<A,T> >::compl_bits(nrv, x);
+ return nrv;
+}
+
+// Arithmetic and bitwise operators involving integral types
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator += (IntegralT rhs)
+{
+ integral_ops<IntegralT>::add(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator -= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::subtract(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator *= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::multiply(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator /= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::divide(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator %= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::modulo(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator |= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_or(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator &= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_and(*this, rhs);
+ return *this;
+}
+
+template<class A, class T>
+template<typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T>&>::type
+unbounded_uint<A,T>::operator ^= (IntegralT rhs)
+{
+ integral_ops<IntegralT>::bitwise_xor(*this, rhs);
+ return *this;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator + (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv += rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator - (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv -= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator * (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv *= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator / (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv /= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator % (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv %= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator | (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv |= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator & (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv &= rhs;
+ return nrv;
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, unbounded_uint<A,T> >::type
+operator ^ (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv ^= rhs;
+ return nrv;
+}
+
+// Arithmetic and bitwise operators involving character strings
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator += (const charT* s)
+{
+ return *this += unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator -= (const charT* s)
+{
+ return *this -= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator *= (const charT* s)
+{
+ return *this *= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator /= (const charT* s)
+{
+ return *this /= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator %= (const charT* s)
+{
+ return *this %= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator |= (const charT* s)
+{
+ return *this |= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator &= (const charT* s)
+{
+ return *this &= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT>
+inline unbounded_uint<A,T>& unbounded_uint<A,T>::operator ^= (const charT* s)
+{
+ return *this ^= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator + (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv += unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator - (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv -= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator * (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv *= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator / (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv /= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator % (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv %= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator | (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv |= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator & (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv &= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT>
+inline
+unbounded_uint<A,T> operator ^ (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv ^= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+
+// Arithmetic and bitwise operators involving basic_string
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator += (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this += unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator -= (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this -= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator *= (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this *= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator /= (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this /= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator %= (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this %= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator |= (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this |= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator &= (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this &= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T>
+template<typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>&
+unbounded_uint<A,T>::operator ^= (const std::basic_string<charT,traits,Alloc>& s)
+{
+ return *this ^= unbounded_uint<A,T>(s);
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator + (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv += unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator - (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv -= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator * (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv *= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator / (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv /= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator % (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv %= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator | (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv |= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator & (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv &= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+template<class A, class T, typename charT, class traits, class Alloc>
+inline unbounded_uint<A,T>
+operator ^ (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,traits,Alloc>& rhs)
+{
+ unbounded_uint<A,T> nrv(lhs);
+ nrv ^= unbounded_uint<A,T>(rhs);
+ return nrv;
+}
+
+
+// compare unbounded_uint to unbounded_uint
+template<class A, class T>
+inline bool
+operator == (const unbounded_uint<A,T>& lhs, const unbounded_uint<A,T>& rhs)
+{
+ return (lhs.size() == rhs.size()) &&
+ std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template<class A, class T>
+inline bool
+operator != (const unbounded_uint<A,T>& lhs, const unbounded_uint<A,T>& rhs)
+{
+ return !(lhs == rhs);
+}
+
+template<class A, class T>
+bool
+operator < (const unbounded_uint<A,T>& lhs, const unbounded_uint<A,T>& rhs)
+{
+ if (lhs.size() < rhs.size())
+ return true;
+ if (lhs.size() > rhs.size())
+ return false;
+
+ // TODO ops_type::compare_magnitude vs lexicographical_compare
+ return std::lexicographical_compare(lhs.rbegin(), lhs.rend(),
+ rhs.rbegin(), rhs.rend());
+}
+
+template<class A, class T>
+inline bool
+operator > (const unbounded_uint<A,T>& lhs, const unbounded_uint<A,T>& rhs)
+{
+ return rhs < lhs;
+}
+
+template<class A, class T>
+inline bool
+operator <= (const unbounded_uint<A,T>& lhs, const unbounded_uint<A,T>& rhs)
+{
+ return !(rhs < lhs);
+}
+
+template<class A, class T>
+inline bool
+operator >= (const unbounded_uint<A,T>& lhs, const unbounded_uint<A,T>& rhs)
+{
+ return !(lhs < rhs);
+}
+
+// compare unbounded_uint to integral
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (const unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_uint_integral_ops<
+ unbounded_uint<A,T>, IntegralT>::equal(lhs, rhs);
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator != (const unbounded_uint<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 unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ return detail::unbounded_uint_integral_ops<
+ unbounded_uint<A,T>, IntegralT>::less(lhs, rhs);
+}
+
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator > (const unbounded_uint<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 unbounded_uint<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 unbounded_uint<A,T>& lhs, IntegralT rhs)
+{
+ return !(lhs < rhs);
+}
+
+// compare integral to unbounded_uint
+template<class A, class T, typename IntegralT>
+inline
+typename enable_if<is_integral<IntegralT>, bool>::type
+operator == (IntegralT lhs, const unbounded_uint<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 unbounded_uint<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 unbounded_uint<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 unbounded_uint<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 unbounded_uint<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 unbounded_uint<A,T>& rhs)
+{
+ return rhs <= lhs;
+}
+
+// compare unbounded_uint to const charT*
+template<class A, class T, typename charT>
+bool
+operator == (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ detail::from_string_converter<unbounded_uint<A,T> > conv;
+ conv.detect_properties(rhs, rhs + std::char_traits<charT>::length(rhs));
+
+ if (conv.total_length == 0)
+ {
+ if (lhs.is_uninitialized())
+ return true;
+ else
+ return false;
+ }
+
+ // if we see a minus sign and it is not "-0" then return false
+ if (!conv.is_positive && !(conv.length == 0 && conv.radix == 8))
+ return false;
+ // TODO that also means we skip scanning the string for invalid characters
+
+ unbounded_uint<A,T> tmp;
+ conv.convert(tmp, rhs, rhs + std::char_traits<charT>::length(rhs));
+
+ return lhs == tmp;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator != (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ return lhs != unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator < (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ return lhs < unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator > (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ return lhs > unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator <= (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ return lhs <= unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator >= (const unbounded_uint<A,T>& lhs, const charT* rhs)
+{
+ return lhs >= unbounded_uint<A,T>(rhs);
+}
+
+// comparison const charT* to unbounded_uint
+template<class A, class T, typename charT>
+inline bool
+operator == (const charT* lhs, const unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<A,T>(lhs) == rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator != (const charT* lhs, const unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<A,T>(lhs) != rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator < (const charT* lhs, const unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<A,T>(lhs) < rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator > (const charT* lhs, const unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<A,T>(lhs) > rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator <= (const charT* lhs, const unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<A,T>(lhs) <= rhs;
+}
+
+template<class A, class T, typename charT>
+inline bool
+operator >= (const charT* lhs, const unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<A,T>(lhs) >= rhs;
+}
+
+// compare unbounded_uint to basic_string
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator == (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs == unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator != (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs != unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator < (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs < unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator > (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs > unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator <= (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs <= unbounded_uint<A,T>(rhs);
+}
+
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator >= (const unbounded_uint<A,T>& lhs,
+ const std::basic_string<charT,Traits,Alloc>& rhs)
+{
+ return lhs >= unbounded_uint<A,T>(rhs);
+}
+
+// compare basic_string to unbounded_uint
+template<class A, class T, class charT, class Traits, class Alloc>
+inline bool
+operator == (const std::basic_string<charT,Traits,Alloc>& lhs,
+ const unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<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 unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<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 unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<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 unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<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 unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<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 unbounded_uint<A,T>& rhs)
+{
+ return unbounded_uint<A,T>(lhs) >= rhs;
+}
+
+// Input/Output
+template<class A, class T, typename charT, class traits>
+std::basic_istream<charT, traits>&
+operator >> (std::basic_istream<charT, traits>& is, unbounded_uint<A,T>& x)
+{
+ typename std::basic_istream<charT, traits>::sentry sentry(is);
+ if (!sentry)
+ return is;
+
+ // TODO we read into a string first which costs memory and std::string
+ // allocator is not under user control. We should convert incoming digits
+ // directly. Actually we should check what is the fastest way.
+ std::string s;
+
+ const std::istreambuf_iterator<charT, traits> end;
+ std::istreambuf_iterator<charT, traits> c(is);
+
+ // TODO we should stop if we see a minus sign
+ 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 unbounded_uint<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 unbounded_uint<A,T>& x)
+{
+ // TODO same as above, we should output digits directly to the stream
+ return os << x.template to_string<std::string>(os.flags());
+}
+
+
+template<class A, class T>
+inline
+unbounded_uint<A,T> abs(const unbounded_uint<A,T>& x)
+{
+ return x;
+}
+
+template<class A, class T>
+inline
+unbounded_uint<A,T> gcd(const unbounded_uint<A,T>& a,
+ const unbounded_uint<A,T>& b)
+{
+ unbounded_uint<A,T> z;
+ detail::gcd_finder<unbounded_uint<A,T> >::gcd(z, a, b);
+ return z;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class A, class T, class... Integer>
+unbounded_uint<A,T> gcd(const unbounded_uint<A,T>& a,
+ const unbounded_uint<A,T>& b,
+ const Integer&... args)
+{
+ return gcd(gcd(a, b), args...);
+}
+#endif
+
+template<class A, class T>
+inline
+unbounded_uint<A,T> lcm(const unbounded_uint<A,T>& a,
+ const unbounded_uint<A,T>& b)
+{
+ unbounded_uint<A,T> z;
+ detail::lcm_finder<unbounded_uint<A,T> >::lcm(z, a, b);
+ return z;
+}
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+template<class A, class T, class... Integer>
+unbounded_uint<A,T> lcm(const unbounded_uint<A,T>& a,
+ const unbounded_uint<A,T>& b,
+ const Integer&... args)
+{
+ return lcm(lcm(a, b), args...);
+}
+#endif
+
+template<class A, class T>
+inline
+unbounded_uint<A,T>
+pow(const unbounded_uint<A,T>& x, typename unbounded_uint<A,T>::size_type y)
+{
+ unbounded_uint<A,T> z;
+ detail::power<unbounded_uint<A,T> >::pow(z, x, y);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_uint<A,T>
+pow(const unbounded_uint<A,T>& x, const unbounded_uint<A,T>& y)
+{
+ unbounded_uint<A,T> z;
+ detail::power<unbounded_uint<A,T> >::pow(z, x, y);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_uint<A,T> sqrt(const unbounded_uint<A,T>& x)
+{
+ unbounded_uint<A,T> z;
+ detail::root<unbounded_uint<A,T> >::sqrt(z, x);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_uint<A,T> nth_root(typename unbounded_uint<A,T>::size_type n,
+ const unbounded_uint<A,T>& x)
+{
+ unbounded_uint<A,T> z;
+ detail::root<unbounded_uint<A,T> >::nth_root(z, n, x);
+ return z;
+}
+
+template<class A, class T>
+inline
+unbounded_uint<A,T> nth_root(const unbounded_uint<A,T>& n,
+ const unbounded_uint<A,T>& x)
+{
+ unbounded_uint<A,T> z;
+ detail::root<unbounded_uint<A,T> >::nth_root(z, n, x);
+ return z;
+}
+
+template<class A, class T>
+inline
+int jacobi(const unbounded_uint<A,T>& x, const unbounded_uint<A,T>& y)
+{
+ return detail::jacobi(x, y);
+}
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Copied: sandbox/mp_math/boost/mp_math/integer_serialization.hpp (from r54148, /sandbox/mp_math/boost/mp_math/mp_int_serialization.hpp)
==============================================================================
--- /sandbox/mp_math/boost/mp_math/mp_int_serialization.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer_serialization.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -1,18 +1,51 @@
-// Copyright Kevin Sopp 2008.
+// Copyright Kevin Sopp 2008 - 2009.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#include <boost/mp_math/mp_int/mp_int_fwd.hpp>
+#ifndef BOOST_MP_MATH_INTEGER_SERIALIZATION_HPP
+#define BOOST_MP_MATH_INTEGER_SERIALIZATION_HPP
+
+#include <boost/mp_math/integer/integer_fwd.hpp>
+#include <boost/serialization/base_object.hpp>
 #include <boost/serialization/split_free.hpp>
 #include <boost/serialization/string.hpp>
 
+
 namespace boost {
 namespace serialization {
 
+
+template<class Archive, class A, class T>
+void save(Archive& ar,
+ const boost::mp_math::unbounded_int<A,T>& x,
+ const unsigned int /*version*/)
+{
+ const std::string s = x.template to_string<std::string>(std::ios_base::hex);
+ ar & s;
+}
+
+template<class Archive, class A, class T>
+void load(Archive& ar,
+ boost::mp_math::unbounded_int<A,T>& x,
+ const unsigned int /*version*/)
+{
+ std::string s;
+ ar & s;
+ x.template assign(s, std::ios_base::hex);
+}
+
+template<class Archive, class A, class T>
+inline void serialize(Archive& ar,
+ boost::mp_math::unbounded_int<A,T>& x,
+ const unsigned int version)
+{
+ split_free(ar, x, version);
+}
+
 template<class Archive, class A, class T>
 void save(Archive& ar,
- const boost::mp_math::mp_int<A,T>& x,
+ const boost::mp_math::unbounded_uint<A,T>& x,
           const unsigned int /*version*/)
 {
   const std::string s = x.template to_string<std::string>(std::ios_base::hex);
@@ -21,7 +54,7 @@
 
 template<class Archive, class A, class T>
 void load(Archive& ar,
- boost::mp_math::mp_int<A,T>& x,
+ boost::mp_math::unbounded_uint<A,T>& x,
           const unsigned int /*version*/)
 {
   std::string s;
@@ -31,12 +64,31 @@
 
 template<class Archive, class A, class T>
 inline void serialize(Archive& ar,
- boost::mp_math::mp_int<A,T>& x,
+ boost::mp_math::unbounded_uint<A,T>& x,
                       const unsigned int version)
 {
- boost::serialization::split_free(ar, x, version);
+ split_free(ar, x, version);
 }
 
+template<class Archive, bool S, class A, class T>
+inline void serialize(Archive & ar,
+ boost::mp_math::unbounded<S,A,T>& x,
+ const unsigned int /*version*/)
+{
+ ar & base_object<typename boost::mp_math::unbounded<S,A,T>::base_type>(x);
+}
+
+template<class Archive, class Type>
+inline void serialize(Archive & ar,
+ boost::mp_math::integer<Type>& x,
+ const unsigned int /*version*/)
+{
+ ar & base_object<Type>(x);
+}
+
+
 } // namespace serialization
 } // namespace boost
 
+#endif
+

Added: sandbox/mp_math/boost/mp_math/libtom.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/libtom.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,12 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_MATH_LIBTOM_HPP
+#define BOOST_MP_MATH_LIBTOM_HPP
+
+#include <boost/mp_math/integer/libtom_integer.hpp>
+
+#endif
+

Deleted: sandbox/mp_math/boost/mp_math/mp_int.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,21 +0,0 @@
-// 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_fwd.hpp>
-#include <boost/mp_math/mp_int/mp_int.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/modinv.hpp>
-#include <boost/mp_math/mp_int/modpow.hpp>
-#include <boost/mp_math/mp_int/numeric_limits.hpp>
-#include <boost/mp_math/mp_int/prime.hpp>
-#include <boost/mp_math/mp_int/root.hpp>
-
-#endif

Deleted: sandbox/mp_math/boost/mp_math/mp_int_serialization.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/mp_int_serialization.hpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,42 +0,0 @@
-// 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/mp_int_fwd.hpp>
-#include <boost/serialization/split_free.hpp>
-#include <boost/serialization/string.hpp>
-
-namespace boost {
-namespace serialization {
-
-template<class Archive, class A, class T>
-void save(Archive& ar,
- const boost::mp_math::mp_int<A,T>& x,
- const unsigned int /*version*/)
-{
- const std::string s = x.template to_string<std::string>(std::ios_base::hex);
- ar & s;
-}
-
-template<class Archive, class A, class T>
-void load(Archive& ar,
- boost::mp_math::mp_int<A,T>& x,
- const unsigned int /*version*/)
-{
- std::string s;
- ar & s;
- x.template assign(s, std::ios_base::hex);
-}
-
-template<class Archive, class A, class T>
-inline void serialize(Archive& ar,
- boost::mp_math::mp_int<A,T>& x,
- const unsigned int version)
-{
- boost::serialization::split_free(ar, x, version);
-}
-
-} // namespace serialization
-} // namespace boost
-

Added: sandbox/mp_math/libs/mp_math/examples/answer.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/examples/answer.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,46 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mp_math/integer.hpp>
+
+typedef boost::mp_math::integer<> int_type;
+
+
+int main(int, char**)
+{
+ int_type x(2), y(0x257);
+
+ x = pow(x, 101);
+
+ x = modpow(x, y, int_type(257));
+
+ while (y > 2)
+ {
+ x *= y;
+ --y;
+ }
+
+ x = y + y + y * x % (int_type(12));
+
+ for (int i = 0; i < 15; ++i)
+ {
+ x -= x * y;
+ y += 15;
+ x += i;
+ };
+
+ x *= -1;
+
+ x = sqrt(x);
+
+ // now x should be 0x66d74da264f9
+ std::cout << std::hex << std::showbase << "The answer is " << x << "." << std::endl;
+
+
+ return 0;
+}
+
+
+

Added: sandbox/mp_math/libs/mp_math/examples/drops_in_the_ocean.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/examples/drops_in_the_ocean.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,63 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// calculate the number of water drops in earth's oceans
+
+#include <boost/timer.hpp>
+#include <boost/mp_math/integer.hpp>
+#include <boost/mp_math/integer/gmp_integer.hpp>
+
+typedef boost::mp_math::integer<> int_type;
+
+
+int main(int, char**)
+{
+ // assume that the oceans have a volume of 1.3 billion km^3
+ // assume that one drop has a volume of 0.05 ml
+ const unsigned long ocean_vol = 1300000000UL;
+ const unsigned long drops_per_ml = 20;
+
+ // there are 1000 ml in 1 liter and 1 liter = 1 dm^3
+
+ int_type num_drops = 1; // start with one drop
+
+ num_drops *= drops_per_ml; // now we have the number of drops per ml
+ num_drops *= 1000; // now we have the number of drops per liter
+ num_drops *= 1000; // 1 m^3 = 1000 dm^ 3
+ num_drops *= 1000000000UL; // 1 km^3 = 1000000000 m^3
+ num_drops *= ocean_vol;
+
+ std::cout << "Earth's oceans consist of " << num_drops << " water drops!"
+ << std::endl;
+
+
+ int_type counter = num_drops;
+
+ boost::timer t;
+ while (t.elapsed() < 2.0)
+ --counter;
+
+ //counter /= 2; // FIXME!! this makes a larger number out of counter
+ //c1 = 25999999999999999995604718
+ //c2 = 26000000005912711854358254
+
+ const int_type difference = (num_drops - counter) / 2;
+ int_type years = num_drops / difference;
+
+ years /= 60;
+ years /= 60;
+ years /= 24;
+ years /= 365;
+
+ std::cout << "This computer can count about " << difference << " water drops "
+ << "per second.\n"
+ << "Counting all water drops would take about " << years
+ << " years on this computer." << std::endl;
+
+ return 0;
+}
+
+
+

Added: sandbox/mp_math/libs/mp_math/examples/gmp.cpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/examples/gmp.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,24 @@
+// Copyright Kevin Sopp 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mp_math/integer.hpp>
+#include <boost/mp_math/gmp.hpp>
+
+typedef boost::mp_math::integer<boost::mp_math::gmp_integer<> > int_type;
+
+int main(int, char**)
+{
+ int_type x, y;
+
+ x = 0x1223;
+ y = "0x2984389248923984ababab";
+
+ const int_type z = pow(y, x);
+
+ std::cout << z << std::endl;
+
+ return 0;
+}
+

Added: sandbox/mp_math/libs/mp_math/examples/jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/mp_math/libs/mp_math/examples/jamfile.v2 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -0,0 +1,40 @@
+# Copyright Kevin Sopp 2009.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+project
+ :
+ requirements
+ <include>../../../..
+ <include>.
+ <link>static
+ ;
+
+
+exe drops_in_the_ocean
+ :
+ drops_in_the_ocean.cpp
+ :
+ <variant>release
+ ;
+
+exe answer
+ :
+ answer.cpp
+ :
+ <variant>release
+ ;
+
+
+lib gmp_library : : <name>gmp ;
+
+exe gmp
+ :
+ gmp.cpp
+ gmp_library
+ :
+ <variant>release
+ ;
+
+

Modified: sandbox/mp_math/libs/mp_math/index.html
==============================================================================
--- sandbox/mp_math/libs/mp_math/index.html (original)
+++ sandbox/mp_math/libs/mp_math/index.html 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
@@ -5,7 +5,7 @@
 <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" />
+ <meta http-equiv="refresh" content="0; URL=doc/html/index.html" />
 </head>
 
 <body>

Deleted: sandbox/mp_math/libs/mp_math/test/add.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/add.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,217 +0,0 @@
-// 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");
-}
-

Deleted: sandbox/mp_math/libs/mp_math/test/bitmanipulation.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/bitmanipulation.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,118 +0,0 @@
-// Copyright Kevin Sopp 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include <boost/test/unit_test.hpp>
-#include "prerequisite.hpp"
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits1, mp_int_type, mp_int_types)
-{
- mp_int_type x("0xff00000000ff");
- x.set_bits(8, 40);
- BOOST_CHECK_EQUAL(x, "0xffffffffffff");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits2, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x8000");
- x.set_bits(2, 7);
- BOOST_CHECK_EQUAL(x, "0x807c");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits3, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x80000000000000");
- x.set_bits(12, 13);
- BOOST_CHECK_EQUAL(x, "0x80000000001000");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits4, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x8000000000000000");
- x.set_bits(0, 18);
- BOOST_CHECK_EQUAL(x, "0x800000000003FFFF");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(set_bits5, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x80000000");
- x.set_bits(8, 16);
- BOOST_CHECK_EQUAL(x, "0x8000FF00");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits1, mp_int_type, mp_int_types)
-{
- mp_int_type x("0xffffffffffff");
- x.clear_bits(8, 40);
- BOOST_CHECK_EQUAL(x, "0xff00000000ff");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits2, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x807c");
- x.clear_bits(2, 7);
- BOOST_CHECK_EQUAL(x, "0x8000");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits3, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x80000000001000");
- x.clear_bits(12, 13);
- BOOST_CHECK_EQUAL(x, "0x80000000000000");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits4, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x800000000003FFFF");
- x.clear_bits(0, 18);
- BOOST_CHECK_EQUAL(x, "0x8000000000000000");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(clear_bits5, mp_int_type, mp_int_types)
-{
- mp_int_type x("0x8000FF00");
- x.clear_bits(8, 16);
- BOOST_CHECK_EQUAL(x, "0x80000000");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(truncate1, mp_int_type, mp_int_types)
-{
- mp_int_type x("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- x.truncate(32);
- x.clamp();
- BOOST_CHECK_EQUAL(x, "0xFFFFFFFF");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(truncate2, mp_int_type, mp_int_types)
-{
- mp_int_type x("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- x.truncate(0);
- x.clamp();
- BOOST_CHECK_EQUAL(x, "");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(truncate3, mp_int_type, mp_int_types)
-{
- mp_int_type x("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- x.truncate(1);
- x.clamp();
- BOOST_CHECK_EQUAL(x, "1");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(truncate4, mp_int_type, mp_int_types)
-{
- mp_int_type x("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- x.truncate(31);
- x.clamp();
- BOOST_CHECK_EQUAL(x, "0x7FFFFFFF");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(truncate5, mp_int_type, mp_int_types)
-{
- mp_int_type x("0xFFFFFFFFFFFFFFFFFFFF");
- x.truncate(80);
- x.clamp();
- BOOST_CHECK_EQUAL(x, "0xFFFFFFFFFFFFFFFFFFFF");
-}
-

Deleted: sandbox/mp_math/libs/mp_math/test/bitwise_ops.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/bitwise_ops.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,56 +0,0 @@
-// 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");
-}
-

Deleted: sandbox/mp_math/libs/mp_math/test/bool_conversion.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/bool_conversion.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,40 +0,0 @@
-// 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);
-}
-

Deleted: sandbox/mp_math/libs/mp_math/test/cmp.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/cmp.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,171 +0,0 @@
-// Copyright Kevin Sopp 2008 - 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#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_type1, 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_integral_type2, mp_int_type, mp_int_types)
-{
- const mp_int_type x("0x100000000");
- BOOST_CHECK_LE(1, x);
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_lt_integral_type3, mp_int_type, mp_int_types)
-{
- const mp_int_type x("-0x100000000");
- BOOST_CHECK_LT(x, -1);
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_lt_integral_type4, mp_int_type, mp_int_types)
-{
- mp_int_type x(std::numeric_limits<int>::min());
- x -= 1;
- BOOST_CHECK_LT(x, std::numeric_limits<int>::min());
-}
-
-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);
-}
-
-

Deleted: sandbox/mp_math/libs/mp_math/test/compile_all.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/compile_all.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,96 +0,0 @@
-// 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;
-}
-

Deleted: sandbox/mp_math/libs/mp_math/test/ctors.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/ctors.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,188 +0,0 @@
-// 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, 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, 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

Deleted: sandbox/mp_math/libs/mp_math/test/div.cpp
==============================================================================
--- sandbox/mp_math/libs/mp_math/test/div.cpp 2009-06-22 14:57:19 EDT (Mon, 22 Jun 2009)
+++ (empty file)
@@ -1,112 +0,0 @@
-// 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(divide4, mp_int_type, mp_int_types)
-{
- const mp_int_type x("0x89ab89745cc653de58eecc8f8a874120065ea545f6f5f");
- const mp_int_type y("0x1889ba8a789456adfc8005b1");
- const mp_int_type z = x / y;
- BOOST_CHECK_EQUAL(z, "0x59c48aa7a1446110b31f70");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(divide5, mp_int_type, mp_int_types)
-{
- const mp_int_type x("0x1889ba8a789456adfc8005b1");
- const mp_int_type y("0x1889ba8a789456adfc8005b2");
- const mp_int_type z = x / y;
- BOOST_CHECK_EQUAL(z, "0");
-}
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(divide_by_2, mp_int_type, mp_int_types)
-{
- mp_int_type x("263825472");
- 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_EQU