|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r68747 - in trunk: boost/random/detail libs/random/test
From: steven_at_[hidden]
Date: 2011-02-09 11:49:51
Author: steven_watanabe
Date: 2011-02-09 11:49:49 EST (Wed, 09 Feb 2011)
New Revision: 68747
URL: http://svn.boost.org/trac/boost/changeset/68747
Log:
Fix const_mod to work in all cases.
Added:
trunk/libs/random/test/test_const_mod.cpp (contents, props changed)
Text files modified:
trunk/boost/random/detail/const_mod.hpp | 326 ++++++++++-----------------------------
trunk/libs/random/test/Jamfile.v2 | 1
2 files changed, 88 insertions(+), 239 deletions(-)
Modified: trunk/boost/random/detail/const_mod.hpp
==============================================================================
--- trunk/boost/random/detail/const_mod.hpp (original)
+++ trunk/boost/random/detail/const_mod.hpp 2011-02-09 11:49:49 EST (Wed, 09 Feb 2011)
@@ -17,9 +17,11 @@
#define BOOST_RANDOM_CONST_MOD_HPP
#include <cassert>
+#include <algorithm>
#include <boost/static_assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer_traits.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/random/detail/disable_warnings.hpp>
@@ -33,57 +35,29 @@
* IntType must be an integral type.
*/
-namespace detail {
-
- template<bool is_signed>
- struct do_add
- { };
-
- template<>
- struct do_add<true>
- {
- template<class IntType>
- static IntType add(IntType m, IntType x, IntType c)
- {
- if (x < m - c)
- return x + c;
- else
- return x - (m-c);
- }
- };
-
- template<>
- struct do_add<false>
- {
- template<class IntType>
- static IntType add(IntType, IntType, IntType)
- {
- // difficult
- assert(!"const_mod::add with c too large");
- return 0;
- }
- };
-} // namespace detail
-
-#if !(defined(__BORLANDC__) && (__BORLANDC__ == 0x560))
-
template<class IntType, IntType m>
class const_mod
{
public:
static IntType add(IntType x, IntType c)
{
- if(c == 0)
+ if(((unsigned_m() - 1) & unsigned_m()) == 0)
+ return (unsigned_type(x) + unsigned_type(c)) & (unsigned_m() - 1);
+ else if(c == 0)
return x;
- else if(c <= traits::const_max - m) // i.e. m+c < max
- return add_small(x, c);
+ else if(x < m - c)
+ return x + c;
else
- return detail::do_add<traits::is_signed>::add(m, x, c);
+ return x - (m - c);
}
static IntType mult(IntType a, IntType x)
{
- if(a == 1)
+ if(((unsigned_m() - 1) & unsigned_m()) == 0)
+ return unsigned_type(a) * unsigned_type(x) & (unsigned_m() - 1);
+ else if(a == 0)
+ return 0;
+ else if(a == 1)
return x;
else if(m <= traits::const_max/a) // i.e. a*m <= max
return mult_small(a, x);
@@ -91,37 +65,31 @@
return mult_schrage(a, x);
else if(x == 1)
return a;
- else {
- // difficult
- assert(!"const_mod::mult with a too large");
- return 0;
- }
+ else
+ return mult_general(a, x);
}
static IntType mult_add(IntType a, IntType x, IntType c)
{
- if(m <= (traits::const_max-c)/a) // i.e. a*m+c <= max
+ if(((unsigned_m() - 1) & unsigned_m()) == 0)
+ return (unsigned_type(a) * unsigned_type(x) + unsigned_type(c)) & (unsigned_m() - 1);
+ else if(a == 0)
+ return c;
+ else if(m <= (traits::const_max-c)/a) // i.e. a*m+c <= max
return (a*x+c) % m;
else
return add(mult(a, x), c);
}
static IntType invert(IntType x)
- { return x == 0 ? 0 : invert_euclidian(x); }
+ { return x == 0 ? 0 : (m == 0? invert_euclidian0(x) : invert_euclidian(x)); }
private:
typedef integer_traits<IntType> traits;
+ typedef typename make_unsigned<IntType>::type unsigned_type;
const_mod(); // don't instantiate
- static IntType add_small(IntType x, IntType c)
- {
- x += c;
- if(x >= m)
- x -= m;
- return x;
- }
-
static IntType mult_small(IntType a, IntType x)
{
return a*x % m;
@@ -134,27 +102,60 @@
assert(r < q); // check that overflow cannot happen
- value = a*(value%q) - r*(value/q);
- // An optimizer bug in the SGI MIPSpro 7.3.1.x compiler requires this
- // convoluted formulation of the loop (Synge Todo)
- for(;;) {
- if (value > 0)
- break;
- value += m;
+ return sub(a*(value%q), r*(value/q));
+ }
+
+ static IntType mult_general(IntType a, IntType b) {
+ IntType q, r;
+ IntType value = 0;
+
+ while(true) {
+ if(a == 0 || b <= traits::const_max/a)
+ return add(value, IntType(a * b % m));
+
+ if(b < a) std::swap(a, b);
+ q = m / a;
+ r = m % a;
+
+ value = add(value, IntType(a*(b%q)));
+
+ a = r;
+ b = IntType(b/q);
+ if(a == 0 || b <= traits::const_max/a)
+ return sub(value, IntType(a * b % m));
+
+ if(b < a) std::swap(a, b);
+ q = m / a;
+ r = m % a;
+
+ value = sub(value, IntType(a*(b%q)));
+
+ a = r;
+ b = IntType(b/q);
}
- return value;
+ }
+
+ static IntType sub(IntType a, IntType b)
+ {
+ if(a < b)
+ return m - (b - a);
+ else
+ return a - b;
+ }
+
+ static unsigned_type unsigned_m()
+ {
+ if(m == 0) {
+ return unsigned_type((std::numeric_limits<IntType>::max)()) + 1;
+ } else {
+ return unsigned_type(m);
+ }
}
// invert c in the finite field (mod m) (m must be prime)
static IntType invert_euclidian(IntType c)
{
// we are interested in the gcd factor for c, because this is our inverse
- BOOST_STATIC_ASSERT(m > 0);
-#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
- assert(boost::integer_traits<IntType>::is_signed);
-#elif !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)
- BOOST_STATIC_ASSERT(boost::integer_traits<IntType>::is_signed);
-#endif
assert(c > 0);
IntType l1 = 0;
IntType l2 = 1;
@@ -162,201 +163,48 @@
IntType p = m;
for(;;) {
IntType q = p / n;
- l1 -= q * l2; // this requires a signed IntType!
+ l1 += q * l2;
p -= q * n;
if(p == 0)
- return (l2 < 1 ? l2 + m : l2);
+ return l2;
IntType q2 = n / p;
- l2 -= q2 * l1;
+ l2 += q2 * l1;
n -= q2 * p;
if(n == 0)
- return (l1 < 1 ? l1 + m : l1);
- }
- }
-};
-
-// The modulus is exactly the word size: rely on machine overflow handling.
-// Due to a GCC bug, we cannot partially specialize in the presence of
-// template value parameters.
-template<>
-class const_mod<unsigned int, 0>
-{
- typedef unsigned int IntType;
-public:
- static IntType add(IntType x, IntType c) { return x+c; }
- static IntType mult(IntType a, IntType x) { return a*x; }
- static IntType mult_add(IntType a, IntType x, IntType c) { return a*x+c; }
-
- // m is not prime, thus invert is not useful
-private: // don't instantiate
- const_mod();
-};
-
-template<>
-class const_mod<unsigned long, 0>
-{
- typedef unsigned long IntType;
-public:
- static IntType add(IntType x, IntType c) { return x+c; }
- static IntType mult(IntType a, IntType x) { return a*x; }
- static IntType mult_add(IntType a, IntType x, IntType c) { return a*x+c; }
-
- // m is not prime, thus invert is not useful
-private: // don't instantiate
- const_mod();
-};
-
-// the modulus is some power of 2: rely partly on machine overflow handling
-// we only specialize for rand48 at the moment
-#ifndef BOOST_NO_INT64_T
-template<>
-class const_mod<uint64_t, uint64_t(1) << 48>
-{
- typedef uint64_t IntType;
-public:
- static IntType add(IntType x, IntType c) { return c == 0 ? x : mod(x+c); }
- static IntType mult(IntType a, IntType x) { return mod(a*x); }
- static IntType mult_add(IntType a, IntType x, IntType c)
- { return mod(a*x+c); }
- static IntType mod(IntType x) { return x &= ((uint64_t(1) << 48)-1); }
-
- // m is not prime, thus invert is not useful
-private: // don't instantiate
- const_mod();
-};
-#endif /* !BOOST_NO_INT64_T */
-
-#else
-
-//
-// for some reason Borland C++ Builder 6 has problems with
-// the full specialisations of const_mod, define a generic version
-// instead, the compiler will optimise away the const-if statements:
-//
-
-template<class IntType, IntType m>
-class const_mod
-{
-public:
- static IntType add(IntType x, IntType c)
- {
- if(0 == m)
- {
- return x+c;
+ return m - l1;
}
- else
- {
- if(c == 0)
- return x;
- else if(c <= traits::const_max - m) // i.e. m+c < max
- return add_small(x, c);
- else
- return detail::do_add<traits::is_signed>::add(m, x, c);
- }
- }
-
- static IntType mult(IntType a, IntType x)
- {
- if(x == 0)
- {
- return a*x;
- }
- else
- {
- if(a == 1)
- return x;
- else if(m <= traits::const_max/a) // i.e. a*m <= max
- return mult_small(a, x);
- else if(traits::is_signed && (m%a < m/a))
- return mult_schrage(a, x);
- else {
- // difficult
- assert(!"const_mod::mult with a too large");
- return 0;
- }
- }
- }
-
- static IntType mult_add(IntType a, IntType x, IntType c)
- {
- if(m == 0)
- {
- return a*x+c;
- }
- else
- {
- if(m <= (traits::const_max-c)/a) // i.e. a*m+c <= max
- return (a*x+c) % m;
- else
- return add(mult(a, x), c);
- }
- }
-
- static IntType invert(IntType x)
- { return x == 0 ? 0 : invert_euclidian(x); }
-
-private:
- typedef integer_traits<IntType> traits;
-
- const_mod(); // don't instantiate
-
- static IntType add_small(IntType x, IntType c)
- {
- x += c;
- if(x >= m)
- x -= m;
- return x;
}
- static IntType mult_small(IntType a, IntType x)
- {
- return a*x % m;
- }
-
- static IntType mult_schrage(IntType a, IntType value)
- {
- const IntType q = m / a;
- const IntType r = m % a;
-
- assert(r < q); // check that overflow cannot happen
-
- value = a*(value%q) - r*(value/q);
- while(value <= 0)
- value += m;
- return value;
- }
-
- // invert c in the finite field (mod m) (m must be prime)
- static IntType invert_euclidian(IntType c)
+ // invert c in the finite field (mod m) (c must be relatively prime to m)
+ static IntType invert_euclidian0(IntType c)
{
// we are interested in the gcd factor for c, because this is our inverse
- BOOST_STATIC_ASSERT(m > 0);
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- BOOST_STATIC_ASSERT(boost::integer_traits<IntType>::is_signed);
-#endif
assert(c > 0);
+ if(c == 1) return 1;
IntType l1 = 0;
IntType l2 = 1;
IntType n = c;
IntType p = m;
+ IntType max = (std::numeric_limits<IntType>::max)();
+ IntType q = max / n;
+ assert(max % n != n - 1 && "c must be relatively prime to m.");
+ l1 += q * l2;
+ p = max - q * n + 1;
for(;;) {
- IntType q = p / n;
- l1 -= q * l2; // this requires a signed IntType!
- p -= q * n;
if(p == 0)
- return (l2 < 1 ? l2 + m : l2);
+ return l2;
IntType q2 = n / p;
- l2 -= q2 * l1;
+ l2 += q2 * l1;
n -= q2 * p;
if(n == 0)
- return (l1 < 1 ? l1 + m : l1);
+ return m - l1;
+ q = p / n;
+ l1 += q * l2;
+ p -= q * n;
}
}
};
-
-#endif
-
} // namespace random
} // namespace boost
Modified: trunk/libs/random/test/Jamfile.v2
==============================================================================
--- trunk/libs/random/test/Jamfile.v2 (original)
+++ trunk/libs/random/test/Jamfile.v2 2011-02-09 11:49:49 EST (Wed, 09 Feb 2011)
@@ -11,6 +11,7 @@
project /boost/random/test ;
run random_test.cpp ;
+run test_const_mod.cpp /boost//unit_test_framework ;
run ../example/random_demo.cpp ;
run validate.cpp ;
run test_random_device.cpp /boost//random : : : <link>static : test_random_device ;
Added: trunk/libs/random/test/test_const_mod.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/random/test/test_const_mod.cpp 2011-02-09 11:49:49 EST (Wed, 09 Feb 2011)
@@ -0,0 +1,178 @@
+/* test_const_mod.cpp
+ *
+ * Copyright Steven Watanabe 2011
+ * 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)
+ *
+ * $Id$
+ *
+ */
+
+#include <boost/random/detail/const_mod.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+#define BOOST_TEST_MAIN
+#include <boost/test/unit_test.hpp>
+
+typedef boost::mpl::vector<
+ boost::int8_t,
+ boost::uint8_t
+> int8_types;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_mult8, IntType, int8_types) {
+ for(int i = 0; i < 127; ++i) {
+ for(int j = 0; j < 127; ++j) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 127>::mult(IntType(i), IntType(j))), i * j % 127);
+ }
+ }
+ int modulus = (std::numeric_limits<IntType>::max)() + 1;
+ for(int i = 0; i < modulus; ++i) {
+ for(int j = 0; j < modulus; ++j) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 0>::mult(IntType(i), IntType(j))), i * j % modulus);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_add8, IntType, int8_types) {
+ for(int i = 0; i < 127; ++i) {
+ for(int j = 0; j < 127; ++j) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 127>::add(IntType(i), IntType(j))), (i + j) % 127);
+ }
+ }
+ {
+ const int modulus = boost::integer_traits<IntType>::const_max;
+ for(int i = 0; i < modulus; ++i) {
+ for(int j = 0; j < modulus; ++j) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, modulus>::add(IntType(i), IntType(j))), (i + j) % modulus);
+ }
+ }
+ }
+ {
+ int modulus = (std::numeric_limits<IntType>::max)() + 1;
+ for(int i = 0; i < modulus; ++i) {
+ for(int j = 0; j < modulus; ++j) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 0>::add(IntType(i), IntType(j))), (i + j) % modulus);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_mult_add8, IntType, int8_types) {
+ for(int i = 0; i < 127; i += 5) {
+ for(int j = 0; j < 127; j += 3) {
+ for(int k = 0; k < 127; k += 3) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 127>::mult_add(IntType(i), IntType(j), IntType(k))), (i * j + k) % 127);
+ }
+ }
+ }
+ {
+ int modulus = (std::numeric_limits<IntType>::max)() + 1;
+ for(int i = 0; i < modulus; i += 5) {
+ for(int j = 0; j < modulus; j += 3) {
+ for(int k = 0; k < modulus; k += 3) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 0>::mult_add(IntType(i), IntType(j), IntType(k))), (i * j + k) % modulus);
+ }
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_invert8, IntType, int8_types) {
+ for(int i = 1; i < 127; ++i) {
+ IntType inverse = boost::random::const_mod<IntType, 127>::invert(IntType(i));
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 127>::mult(IntType(i), inverse)), 1);
+ }
+ int modulus = (std::numeric_limits<IntType>::max)() + 1;
+ for(int i = 1; i < modulus; i += 2) {
+ IntType inverse = boost::random::const_mod<IntType, 0>::invert(IntType(i));
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 0>::mult(IntType(i), inverse)), 1);
+ }
+}
+
+typedef boost::mpl::vector<
+ boost::int32_t,
+ boost::uint32_t
+> int32_types;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_mult32, IntType, int32_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult(0, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult(0, 2147483562)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult(2147483562, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult(2147483562, 2147483562)), 1);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult(1234567890, 1234657890)), 813106682);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_add32, IntType, int32_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::add(0, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::add(0, 2147483562)), 2147483562);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::add(2147483562, 0)), 2147483562);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::add(2147483562, 2147483562)), 2147483561);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::add(1234567890, 1234657890)), 321742217);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_mult_add32, IntType, int32_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult_add(0, 0, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult_add(0, 2147483562, 827364)), 827364);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult_add(2147483562, 0, 827364)), 827364);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult_add(2147483562, 2147483562, 2147483562)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult_add(1234567890, 1234657890, 1726384759)), 392007878);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_invert32, IntType, int32_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::invert(0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult_add(0, 0, 0)), 0);
+ IntType inverse;
+ inverse = boost::random::const_mod<IntType, 2147483563>::invert(2147483562);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult(2147483562, inverse)), 1);
+ inverse = boost::random::const_mod<IntType, 2147483563>::invert(1234567890);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563>::mult(1234567890, inverse)), 1);
+}
+
+#if !defined(BOOST_NO_INT64_T)
+
+typedef boost::mpl::vector<
+ boost::int64_t,
+ boost::uint64_t
+> int64_types;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_mult64, IntType, int64_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(0, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(0, 2147483562)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(2147483562, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(2147483562, 2147483562)), 316718521754730848);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(1234567890, 1234657890)), 1524268986129152100);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(1234567890726352938, 1234657890736453927)), 88656187017794672);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_add64, IntType, int64_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::add(0, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::add(0, 2147483562)), 2147483562);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::add(2147483562, 0)), 2147483562);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::add(2147483562, 2147483562)), 4294967124);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::add(1234567890, 1234657890)), 2469225780);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::add(1234567890726352938, 1234657890736453927)), 321742217810068367);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::add(2147483563652738490, 8)), 0);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_mult_add64, IntType, int64_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult_add(0, 0, 0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult_add(0, 2147483562, 827364)), 827364);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult_add(2147483562, 0, 827364)), 827364);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult_add(2147483562, 2147483562, 2147483562)), 316718523902214410);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult_add(1234567890, 1234657890, 1726384759)), 1524268987855536859);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult_add(1234567890726352938, 1234657890736453927, 1726384759726488649)), 1815040946744283321);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(test_invert64, IntType, int64_types) {
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::invert(0)), 0);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult_add(0, 0, 0)), 0);
+ IntType inverse;
+ inverse = boost::random::const_mod<IntType, 2147483563652738498>::invert(7362947769);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(7362947769, inverse)), 1);
+ inverse = boost::random::const_mod<IntType, 2147483563652738498>::invert(1263142436887493875);
+ BOOST_CHECK_EQUAL((boost::random::const_mod<IntType, 2147483563652738498>::mult(1263142436887493875, inverse)), 1);
+}
+
+#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk