diff --git a/include/boost/random/additive_combine.hpp b/include/boost/random/additive_combine.hpp
index 52aeb5d..8e9ab31 100644
--- a/include/boost/random/additive_combine.hpp
+++ b/include/boost/random/additive_combine.hpp
@@ -54,6 +54,8 @@ public:
additive_combine(typename MLCG1::result_type seed1,
typename MLCG2::result_type seed2)
: _mlcg1(seed1), _mlcg2(seed2) { }
+ additive_combine(result_type seed)
+ : _mlcg1(seed), _mlcg2(seed) { }
template additive_combine(It& first, It last)
: _mlcg1(first, last), _mlcg2(first, last) { }
@@ -63,6 +65,12 @@ public:
_mlcg2.seed();
}
+ void seed(result_type seed)
+ {
+ _mlcg1.seed(seed);
+ _mlcg2.seed(seed);
+ }
+
void seed(typename MLCG1::result_type seed1,
typename MLCG2::result_type seed2)
{
diff --git a/include/boost/random/detail/seed.hpp b/include/boost/random/detail/seed.hpp
new file mode 100644
index 0000000..e6fc8b8
--- /dev/null
+++ b/include/boost/random/detail/seed.hpp
@@ -0,0 +1,88 @@
+/* boost random/detail/seed.hpp header file
+ *
+ * Copyright Steven Watanabe 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)
+ *
+ * See http://www.boost.org for most recent version including documentation.
+ *
+ * $Id$
+ */
+
+#ifndef BOOST_RANDOM_DETAIL_SEED_HPP
+#define BOOST_RANDOM_DETAIL_SEED_HPP
+
+#include
+
+#if !defined(BOOST_NO_SFINAE)
+
+#include
+#include
+
+namespace boost {
+namespace random {
+namespace detail {
+
+template
+struct disable_seed : boost::disable_if > {};
+
+template
+struct disable_constructor : disable_seed {};
+
+template
+struct disable_constructor {
+};
+
+#define BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(Self, Generator, gen) \
+ template \
+ explicit Self(Generator& gen, typename ::boost::random::detail::disable_constructor::type* = 0)
+
+#define BOOST_RANDOM_DETAIL_GENERATOR_SEED(Self, Generator, gen) \
+ template \
+ void seed(Generator& gen, typename ::boost::random::detail::disable_seed::type* = 0)
+
+#define BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(Self, T, x) \
+ explicit Self(const T& x)
+
+#define BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(Self, T, x) \
+ void seed(const T& x)
+
+}
+}
+}
+
+#else
+
+#include
+#include
+
+#define BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(Self, Generator, gen) \
+ Self(Self& other) { *this = other; } \
+ Self(const Self& other) { *this = other; } \
+ template \
+ explicit Self(Generator& gen) { \
+ boost_random_constructor_impl(gen, ::boost::is_arithmetic());\
+ } \
+ template \
+ void boost_random_constructor_impl(Generator& gen, ::boost::mpl::false_)
+
+#define BOOST_RANDOM_DETAIL_GENERATOR_SEED(Self, Generator, gen) \
+ template \
+ void seed(Generator& gen) { \
+ boost_random_seed_impl(gen, ::boost::is_arithmetic());\
+ }\
+ template\
+ void boost_random_seed_impl(Generator& gen, ::boost::mpl::false_)
+
+#define BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(Self, T, x) \
+ explicit Self(const T& x) { boost_random_constructor_impl(x, ::boost::mpl::true_()); }\
+ void boost_random_constructor_impl(const T& x, ::boost::mpl::true_)
+
+#define BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(Self, T, x) \
+ void seed(const T& x) { boost_random_seed_impl(x, ::boost::mpl::true_()); }\
+ void boost_random_seed_impl(const T& x, ::boost::mpl::true_)
+
+#endif
+
+#endif
diff --git a/include/boost/random/discard_block.hpp b/include/boost/random/discard_block.hpp
index da3f9b1..5c724fa 100644
--- a/include/boost/random/discard_block.hpp
+++ b/include/boost/random/discard_block.hpp
@@ -43,6 +43,7 @@ public:
discard_block() : _rng(), _n(0) { }
explicit discard_block(const base_type & rng) : _rng(rng), _n(0) { }
+ template explicit discard_block(T s) : _rng(s), _n(0) {}
template discard_block(It& first, It last)
: _rng(first, last), _n(0) { }
void seed() { _rng.seed(); _n = 0; }
diff --git a/include/boost/random/lagged_fibonacci.hpp b/include/boost/random/lagged_fibonacci.hpp
index 25f9176..fa5069d 100644
--- a/include/boost/random/lagged_fibonacci.hpp
+++ b/include/boost/random/lagged_fibonacci.hpp
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#include
namespace boost {
@@ -267,9 +268,10 @@ public:
BOOST_STATIC_CONSTANT(unsigned int, short_lag = q);
lagged_fibonacci_01() { init_modulus(); seed(); }
- explicit lagged_fibonacci_01(uint32_t value) { init_modulus(); seed(value); }
- template
- explicit lagged_fibonacci_01(Generator & gen) { init_modulus(); seed(gen); }
+ BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01, uint32_t, value)
+ { init_modulus(); seed(value); }
+ BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(lagged_fibonacci_01, Generator, gen)
+ { init_modulus(); seed(gen); }
template lagged_fibonacci_01(It& first, It last)
{ init_modulus(); seed(first, last); }
// compiler-generated copy ctor and assignment operator are fine
@@ -285,7 +287,8 @@ private:
}
public:
- void seed(uint32_t value = 331u)
+ void seed() { seed(331u); }
+ BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_01, uint32_t, value)
{
minstd_rand0 intgen(value);
seed(intgen);
@@ -294,8 +297,7 @@ public:
// For GCC, moving this function out-of-line prevents inlining, which may
// reduce overall object code size. However, MSVC does not grok
// out-of-line template member functions.
- template
- void seed(Generator & gen)
+ BOOST_RANDOM_DETAIL_GENERATOR_SEED(lagged_fibonacci, Generator, gen)
{
// use pass-by-reference, but wrap argument in pass_through_engine
typedef detail::pass_through_engine ref_gen;
diff --git a/include/boost/random/linear_congruential.hpp b/include/boost/random/linear_congruential.hpp
index 7ea1cd2..f95387d 100644
--- a/include/boost/random/linear_congruential.hpp
+++ b/include/boost/random/linear_congruential.hpp
@@ -212,12 +212,12 @@ public:
int32_t min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
int32_t max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
- explicit rand48(int32_t x0 = 1) : lcf(cnv(x0)) { }
- explicit rand48(uint64_t x0) : lcf(x0) { }
+ rand48() : lcf(cnv(static_cast(1))) {}
+ template explicit rand48(T x0) : lcf(cnv(x0)) { }
template rand48(It& first, It last) : lcf(first, last) { }
// compiler-generated copy ctor and assignment operator are fine
- void seed(int32_t x0 = 1) { lcf.seed(cnv(x0)); }
- void seed(uint64_t x0) { lcf.seed(x0); }
+ void seed() { seed(static_cast(1)); }
+ template void seed(T x0) { lcf.seed(cnv(x0)); }
template void seed(It& first, It last) { lcf.seed(first,last); }
int32_t operator()() { return static_cast(lcf() >> 17); }
@@ -253,8 +253,18 @@ private:
random::linear_congruential lcf;
- static uint64_t cnv(int32_t x)
- { return (static_cast(x) << 16) | 0x330e; }
+ template
+ static uint64_t cnv(T x)
+ {
+ if(sizeof(T) < sizeof(uint64_t)) {
+ return (static_cast(x) << 16) | 0x330e;
+ } else {
+ return(static_cast(x));
+ }
+ }
+ static uint64_t cnv(float x) { return(static_cast(x)); }
+ static uint64_t cnv(double x) { return(static_cast(x)); }
+ static uint64_t cnv(long double x) { return(static_cast(x)); }
};
#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */
diff --git a/include/boost/random/mersenne_twister.hpp b/include/boost/random/mersenne_twister.hpp
index 21080fd..f0058fa 100644
--- a/include/boost/random/mersenne_twister.hpp
+++ b/include/boost/random/mersenne_twister.hpp
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
namespace boost {
namespace random {
@@ -55,28 +56,18 @@ public:
mersenne_twister() { seed(); }
-#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520)
- // Work around overload resolution problem (Gennadiy E. Rozental)
- explicit mersenne_twister(const UIntType& value)
-#else
- explicit mersenne_twister(UIntType value)
-#endif
+ BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(mersenne_twister, UIntType, value)
{ seed(value); }
template mersenne_twister(It& first, It last) { seed(first,last); }
- template
- explicit mersenne_twister(Generator & gen) { seed(gen); }
+ BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(mersenne_twister, Generator, gen)
+ { seed(gen); }
// compiler-generated copy ctor and assignment operator are fine
void seed() { seed(UIntType(5489)); }
-#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520)
- // Work around overload resolution problem (Gennadiy E. Rozental)
- void seed(const UIntType& value)
-#else
- void seed(UIntType value)
-#endif
+ BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister, UIntType, value)
{
// New seeding algorithm from
// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
@@ -93,8 +84,7 @@ public:
// For GCC, moving this function out-of-line prevents inlining, which may
// reduce overall object code size. However, MSVC does not grok
// out-of-line definitions of member function templates.
- template
- void seed(Generator & gen)
+ BOOST_RANDOM_DETAIL_GENERATOR_SEED(mersenne_twister, Generator, gen)
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed);
diff --git a/include/boost/random/subtract_with_carry.hpp b/include/boost/random/subtract_with_carry.hpp
index c30baa6..a6665c6 100644
--- a/include/boost/random/subtract_with_carry.hpp
+++ b/include/boost/random/subtract_with_carry.hpp
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
@@ -86,14 +87,16 @@ public:
#endif
seed();
}
- explicit subtract_with_carry(uint32_t value) { seed(value); }
- template
- explicit subtract_with_carry(Generator & gen) { seed(gen); }
+ BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry, uint32_t, value)
+ { seed(value); }
+ BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry, Generator, gen)
+ { seed(gen); }
template subtract_with_carry(It& first, It last) { seed(first,last); }
// compiler-generated copy ctor and assignment operator are fine
- void seed(uint32_t value = 19780503u)
+ void seed() { seed(19780503u); }
+ BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry, uint32_t, value)
{
random::linear_congruential intgen(value);
seed(intgen);
@@ -102,8 +105,7 @@ public:
// For GCC, moving this function out-of-line prevents inlining, which may
// reduce overall object code size. However, MSVC does not grok
// out-of-line template member functions.
- template
- void seed(Generator & gen)
+ BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry, Generator, gen)
{
// I could have used std::generate_n, but it takes "gen" by value
for(unsigned int j = 0; j < long_lag; ++j)
diff --git a/include/boost/random/uniform_int.hpp b/include/boost/random/uniform_int.hpp
index 8d7f4a0..38823a8 100644
--- a/include/boost/random/uniform_int.hpp
+++ b/include/boost/random/uniform_int.hpp
@@ -23,13 +23,9 @@
#include
#include
#include
-#include
#include
#include
#include
-#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
-#include
-#endif
namespace boost {
@@ -119,45 +115,135 @@ private:
for(;;) {
// concatenate several invocations of the base RNG
// take extra care to avoid overflows
+
+ // limit == floor((range+1)/(brange+1))
+ // Therefore limit*(brange+1) <= range+1
range_type limit;
if(range == (std::numeric_limits::max)()) {
limit = range/(range_type(brange)+1);
- if(range % range_type(brange)+1 == range_type(brange))
+ if(range % (range_type(brange)+1) == range_type(brange))
++limit;
} else {
limit = (range+1)/(range_type(brange)+1);
}
+
// We consider "result" as expressed to base (brange+1):
// For every power of (brange+1), we determine a random factor
range_type result = range_type(0);
range_type mult = range_type(1);
+
+ // loop invariants:
+ // result < mult
+ // mult <= range
while(mult <= limit) {
+ // Postcondition: result <= range, thus no overflow
+ //
+ // limit*(brange+1)<=range+1 def. of limit (1)
+ // eng()-bmin<=brange eng() post. (2)
+ // and mult<=limit. loop condition (3)
+ // Therefore mult*(eng()-bmin+1)<=range+1 by (1),(2),(3) (4)
+ // Therefore mult*(eng()-bmin)+mult<=range+1 rearranging (4) (5)
+ // result()(eng(), bmin) * mult;
+
+ // equivalent to (mult * (brange+1)) == range+1, but avoids overflow.
+ if(mult * range_type(brange) == range - mult + 1) {
+ // The destination range is an integer power of
+ // the generator's range.
+ return(result);
+ }
+
+ // Postcondition: mult <= range
+ //
+ // limit*(brange+1)<=range+1 def. of limit (1)
+ // mult<=limit loop condition (2)
+ // Therefore mult*(brange+1)<=range+1 by (1), (2) (3)
+ // mult*(brange+1)!=range+1 preceding if (4)
+ // Therefore mult*(brange+1) limit loop condition (1)
+ // Suppose range/mult >= brange+1 Assumption (2)
+ // range >= mult*(brange+1) by (2) (3)
+ // range+1 > mult*(brange+1) by (3) (4)
+ // range+1 > (limit+1)*(brange+1) by (1), (4) (5)
+ // (range+1)/(brange+1) > limit+1 by (5) (6)
+ // limit < floor((range+1)/(brange+1)) by (6) (7)
+ // limit==floor((range+1)/(brange+1)) def. of limit (8)
+ // not (2) reductio (9)
+ //
+ // loop postcondition: (range/mult)*mult+(mult-1) >= range
+ //
+ // (range/mult)*mult + range%mult == range identity (1)
+ // range%mult < mult def. of % (2)
+ // (range/mult)*mult+mult > range by (1), (2) (3)
+ // (range/mult)*mult+(mult-1) >= range by (3) (4)
+ //
+ // Note that the maximum value of result at this point is (mult-1),
+ // so after this final step, we generate numbers that can be
+ // at least as large as range. We have to really careful to avoid
+ // overflow in this final addition and in the rejection. Anything
+ // that overflows is larger than range and can thus be rejected.
+
// range/mult < brange+1 -> no endless loop
- result += uniform_int(0, range/mult)(eng) * mult;
- if(result <= range)
- return random::detail::add()(result, min_value);
+ range_type result_increment = uniform_int(0, range/mult)(eng);
+ if((std::numeric_limits::max)() / mult < result_increment) {
+ // The multiplcation would overflow. Reject immediately.
+ continue;
+ }
+ result_increment *= mult;
+ // unsigned integers are guaranteed to wrap on overflow.
+ result += result_increment;
+ if(result < result_increment) {
+ // The addition overflowed. Reject.
+ continue;
+ }
+ if(result > range) {
+ // Too big. Reject.
+ continue;
+ }
+ return random::detail::add()(result, min_value);
}
} else { // brange > range
- if(brange / range > 4 /* quantization_cutoff */ ) {
- // the new range is vastly smaller than the source range,
- // so quantization effects are not relevant
- return boost::uniform_smallint(min_value, max_value)(eng);
- } else {
- // use rejection method to handle cases like 0..5 -> 0..4
- for(;;) {
- base_unsigned result =
- random::detail::subtract()(eng(), bmin);
- // result and range are non-negative, and result is possibly larger
- // than range, so the cast is safe
- if(result <= static_cast(range))
- return random::detail::add()(result, min_value);
+ base_unsigned bucket_size;
+ // it's safe to add 1 to range, as long as we cast it first,
+ // because we know that it is less than brange. However,
+ // we do need to be careful not to cause overflow by adding 1
+ // to brange.
+ if(brange == (std::numeric_limits::max)()) {
+ bucket_size = brange / (static_cast(range)+1);
+ if(brange % (static_cast(range)+1) == static_cast(range)) {
+ ++bucket_size;
}
+ } else {
+ bucket_size = (brange+1) / (static_cast(range)+1);
+ }
+ for(;;) {
+ base_unsigned result =
+ random::detail::subtract()(eng(), bmin);
+ result /= bucket_size;
+ // result and range are non-negative, and result is possibly larger
+ // than range, so the cast is safe
+ if(result <= static_cast(range))
+ return random::detail::add()(result, min_value);
}
}
}
diff --git a/include/boost/random/xor_combine.hpp b/include/boost/random/xor_combine.hpp
index e424275..ad94fd1 100644
--- a/include/boost/random/xor_combine.hpp
+++ b/include/boost/random/xor_combine.hpp
@@ -49,9 +49,12 @@ public:
{ }
xor_combine(const base1_type & rng1, const base2_type & rng2)
: _rng1(rng1), _rng2(rng2) { }
+ xor_combine(const result_type & v)
+ : _rng1(v), _rng2(v) { }
template xor_combine(It& first, It last)
: _rng1(first, last), _rng2( /* advanced by other call */ first, last) { }
void seed() { _rng1.seed(); _rng2.seed(); }
+ void seed(const result_type & v) { _rng1.seed(v); _rng2.seed(v); }
template void seed(It& first, It last)
{
_rng1.seed(first, last);
diff --git a/instantiate.cpp b/instantiate.cpp
index 15bfa7b..b95e446 100644
--- a/instantiate.cpp
+++ b/instantiate.cpp
@@ -129,12 +129,61 @@ void instantiate_real_dist(URNG& urng, RealType /* ignored */)
boost::gamma_distribution(1));
}
+template
+void test_seed(URNG & urng, const T & t) {
+ URNG urng2(t);
+ BOOST_CHECK(urng == urng2);
+ urng2.seed(t);
+ BOOST_CHECK(urng == urng2);
+}
+
+// rand48 uses non-standard seeding
+template
+void test_seed(boost::rand48 & urng, const T & t) {
+ boost::rand48 urng2(t);
+ urng2.seed(t);
+}
+
template
-void instantiate_urng(const std::string & s, const URNG &, const ResultType &)
+void instantiate_seed(const URNG &, const ResultType &) {
+ {
+ URNG urng;
+ URNG urng2;
+ urng2.seed();
+ BOOST_CHECK(urng == urng2);
+ }
+ {
+ int value = 127;
+ URNG urng(value);
+
+ // integral types
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+#if !defined(BOOST_NO_INT64_T)
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+#endif
+
+ // floating point types
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ test_seed(urng, static_cast(value));
+ }
+}
+
+template
+void instantiate_urng(const std::string & s, const URNG & u, const ResultType & r)
{
std::cout << "Basic tests for " << s;
URNG urng;
- urng.seed(); // seed() member function
+ instantiate_seed(u, r); // seed() member function
int a[URNG::has_fixed_range ? 5 : 10]; // compile-time constant
(void) a; // avoid "unused" warning
typename URNG::result_type x1 = urng();
@@ -148,6 +197,8 @@ void instantiate_urng(const std::string & s, const URNG &, const ResultType &)
urng();
urng2 = urng; // copy assignment
BOOST_CHECK(urng == urng2);
+ urng2 = URNG(urng2); // copy constructor, not templated constructor
+ BOOST_CHECK(urng == urng2);
#endif // BOOST_MSVC
const std::vector v(9999u, 0x41);
diff --git a/random-generators.html b/random-generators.html
index de0c965..d01f2b1 100644
--- a/random-generators.html
+++ b/random-generators.html
@@ -35,8 +35,8 @@
Class template
random::mersenne_twister
- Class template
- random::lagged_fibonacci
+ Class template
+ random::lagged_fibonacci_01
Performance
@@ -351,18 +351,18 @@ namespace boost {
typedef random::mersenne_twister< /* ... */ > mt19937;
namespace random {
- template<class FloatType, unsigned int p, unsigned int q>
- class lagged_fibonacci;
+ template<class FloatType, int w, unsigned int p, unsigned int q>
+ class lagged_fibonacci_01;
}
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci607;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci1279;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci2281;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci3217;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci4423;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci9689;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci19937;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci23209;
- typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci44497;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci607;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci1279;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci2281;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci3217;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci4423;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci9689;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci19937;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci23209;
+ typedef random::lagged_fibonacci_01< /* ... */ > lagged_fibonacci44497;
} // namespace boost
@@ -773,7 +773,7 @@ template<class T> void seed(T s)
#include <boost/random/inversive_congruential.hpp>
-template<class IntType, IntType a, IntType b, IntType p>
+template<class IntType, IntType a, IntType b, IntType p, IntType val>
class random::inversive_congruential
{
public:
@@ -789,7 +789,7 @@ public:
IntType operator()();
};
-typedef random::inversive_congruential<int32_t, 9102, 2147483647-36884165, 2147483647> hellekalek1995;
+typedef random::inversive_congruential<int32_t, 9102, 2147483647-36884165, 2147483647, 0> hellekalek1995;
Description
@@ -812,7 +812,8 @@ typedef random::inversive_congruential<int32_t, 9102, 2147483647-36884165, 21
The template parameter IntType shall denote a signed
integral type large enough to hold p; a, b, and p are the parameters of the
- generators.
+ generators. The template parameter val is the validation value checked by
+ validation.
Note: The implementation currently uses the Euclidian Algorithm
to compute the multiplicative inverse. Therefore, the inversive generators
@@ -849,21 +850,19 @@ void seed(IntType y0)
#include <boost/random/mersenne_twister.hpp>
-template<class DataType, int w, int n, int m, int r, DataType a, int u,
-int s, DataType b, int t, DataType c, int l, IntType val>
+template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
+ int s, UIntType b, int t, UIntType c, int l, UIntType val>
class random::mersenne_twister
{
public:
- typedef DataType result_type;
- static const bool has_fixed_range = true;
- static const result_type min_value;
- static const result_type max_value;
+ typedef UIntType result_type;
+ static const bool has_fixed_range = false;
mersenne_twister();
- explicit mersenne_twister(DataType value);
+ explicit mersenne_twister(UIntType value);
template<class Generator> explicit mersenne_twister(Generator & gen);
// compiler-generated copy ctor and assignment operator are fine
void seed();
- void seed(DataType value);
+ void seed(UIntType value);
template<class Generator> void seed(Generator & gen);
result_type operator()();
bool validation(result_type) const;
@@ -918,13 +917,9 @@ template<class Generator> explicit mersenne_twister(Generator & gen)
Effects: Constructs a mersenne_twister and
calls seed(gen).
- Note: When using direct-initialization syntax with an lvalue
- (e.g. in the variable definition Gen gen2(gen);), this
- templated constructor will be preferred over the compiler-generated copy
- constructor. For variable definitions which should copy the state of
- another mersenne_twister, use e.g. Gen gen2 =
- gen;, which is copy-initialization syntax and guaranteed to invoke
- the copy constructor.
+ Note: The copy constructor will always be preferred over the
+ templated constructor. mersenne_twister takes special steps to guarantee
+ this.
Seeding
@@ -953,39 +948,35 @@ template<class Generator> void seed(Generator & gen)
Complexity: Exactly n invocations of
gen.
- Note: When invoking seed with an lvalue, overload
- resolution chooses the function template unless the type of the argument
- exactly matches result_type. For other integer types, you
- should convert the argument to result_type explicitly.
-
The specializations mt11213b and mt19937 are
from the paper cited above.
-
+
Synopsis
#include <boost/random/lagged_fibonacci.hpp>
-template<class FloatType, unsigned int p, unsigned int q>
-class lagged_fibonacci
+template<class FloatType, int w, unsigned int p, unsigned int q>
+class lagged_fibonacci_01
{
public:
typedef FloatType result_type;
static const bool has_fixed_range = false;
+ static const int word_size = w;
static const unsigned int long_lag = p;
static const unsigned int short_lag = q;
result_type min() const { return 0.0; }
result_type max() const { return 1.0; }
- lagged_fibonacci();
- explicit lagged_fibonacci(uint32_t value);
+ lagged_fibonacci_01();
+ explicit lagged_fibonacci_01(uint32_t value);
template<class Generator>
- explicit lagged_fibonacci(Generator & gen);
+ explicit lagged_fibonacci_01(Generator & gen);
// compiler-generated copy ctor and assignment operator are fine
void seed(uint32_t value = 331u);
template<class Generator> void seed(Generator & gen);
@@ -993,15 +984,15 @@ public:
bool validation(result_type x) const;
};
-typedef random::lagged_fibonacci<double, 607, 273> lagged_fibonacci607;
-typedef random::lagged_fibonacci<double, 1279, 418> lagged_fibonacci1279;
-typedef random::lagged_fibonacci<double, 2281, 1252> lagged_fibonacci2281;
-typedef random::lagged_fibonacci<double, 3217, 576> lagged_fibonacci3217;
-typedef random::lagged_fibonacci<double, 4423, 2098> lagged_fibonacci4423;
-typedef random::lagged_fibonacci<double, 9689, 5502> lagged_fibonacci9689;
-typedef random::lagged_fibonacci<double, 19937, 9842> lagged_fibonacci19937;
-typedef random::lagged_fibonacci<double, 23209, 13470> lagged_fibonacci23209;
-typedef random::lagged_fibonacci<double, 44497, 21034> lagged_fibonacci44497;
+typedef random::lagged_fibonacci_01<double, 48, 607, 273> lagged_fibonacci607;
+typedef random::lagged_fibonacci_01<double, 48, 1279, 418> lagged_fibonacci1279;
+typedef random::lagged_fibonacci_01<double, 48, 2281, 1252> lagged_fibonacci2281;
+typedef random::lagged_fibonacci_01<double, 48, 3217, 576> lagged_fibonacci3217;
+typedef random::lagged_fibonacci_01<double, 48, 4423, 2098> lagged_fibonacci4423;
+typedef random::lagged_fibonacci_01<double, 48, 9689, 5502> lagged_fibonacci9689;
+typedef random::lagged_fibonacci_01<double, 48, 19937, 9842> lagged_fibonacci19937;
+typedef random::lagged_fibonacci_01<double, 48, 23209, 13470> lagged_fibonacci23209;
+typedef random::lagged_fibonacci_01<double, 48, 44497, 21034> lagged_fibonacci44497;
Description
@@ -1029,22 +1020,22 @@ typedef random::lagged_fibonacci<double, 44497, 21034> lagged_fibonacci444
Constructors
-lagged_fibonacci()
+lagged_fibonacci_01()
- Effects: Constructs a lagged_fibonacci
+
Effects: Constructs a lagged_fibonacci_01
generator and calls seed().
-explicit lagged_fibonacci(uint32_t value)
+explicit lagged_fibonacci_01(uint32_t value)
- Effects: Constructs a lagged_fibonacci
+
Effects: Constructs a lagged_fibonacci_01
generator and calls seed(value).
-template<class Generator> explicit lagged_fibonacci(Generator & gen)
+template<class Generator> explicit lagged_fibonacci_01(Generator & gen)
- Effects: Constructs a lagged_fibonacci
+
Effects: Constructs a lagged_fibonacci_01
generator and calls seed(gen).
Seeding
@@ -1065,7 +1056,7 @@ template<class Generator> void seed(Generator & gen)
Effects: Sets the state of this
- lagged_fibonacci to the values returned by p
+ lagged_fibonacci_01 to the values returned by p
invocations of uniform_01<gen, FloatType>.
Complexity: Exactly p invocations of
gen.
diff --git a/random_test.cpp b/random_test.cpp
index a1280fd..6a7078e 100644
--- a/random_test.cpp
+++ b/random_test.cpp
@@ -64,7 +64,8 @@ void check_uniform_int(Generator & gen, int iter)
for(int k = 0; k < range; k++)
sum += bucket[k];
double avg = static_cast(sum)/range;
- double threshold = 2*avg/std::sqrt(static_cast(iter));
+ double p = 1 / static_cast(range);
+ double threshold = 2*std::sqrt(static_cast(iter)*p*(1-p));
for(int i = 0; i < range; i++) {
if(std::fabs(bucket[i] - avg) > threshold) {
// 95% confidence interval
@@ -100,11 +101,37 @@ void test_uniform_int(Generator & gen)
// small range => larger range
level_two uint05(uint12, int_gen(-3, 2));
check_uniform_int(uint05, 100000);
+
+ // small range => larger range
+ level_two uint099(uint12, int_gen(0, 99));
+ check_uniform_int(uint099, 100000);
// larger => small range, rejection case
typedef boost::variate_generator level_three;
level_three uint1_4(uint05, int_gen(1, 4));
check_uniform_int(uint1_4, 100000);
+
+ typedef boost::uniform_int int8_gen;
+ typedef boost::variate_generator gen8_t;
+
+ gen8_t gen8_03(gen, int8_gen(0, 3));
+
+ // use the full range of the type, where the destination
+ // range is a power of the source range
+ typedef boost::variate_generator uniform_uint8;
+ uniform_uint8 uint8_0255(gen8_03, int8_gen(0, 255));
+ check_uniform_int(uint8_0255, 100000);
+
+ // use the full range, but a generator whose range is not
+ // a root of the destination range.
+ gen8_t gen8_02(gen, int8_gen(0, 2));
+ uniform_uint8 uint8_0255_2(gen8_02, int8_gen(0, 255));
+ check_uniform_int(uint8_0255_2, 100000);
+
+ // expand the range to a larger type.
+ typedef boost::variate_generator uniform_uint_from8;
+ uniform_uint_from8 uint0300(gen8_03, int_gen(0, 300));
+ check_uniform_int(uint0300, 100000);
}
#if defined(BOOST_MSVC) && _MSC_VER < 1300
@@ -140,10 +167,13 @@ INSTANT(boost::mt11213b)
class ruetti_gen
{
public:
+ ruetti_gen() : state((max)() - 1) {}
typedef boost::uint64_t result_type;
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
- result_type operator()() { return (max)()-1; }
+ result_type operator()() { return state--; }
+private:
+ result_type state;
};
void test_overflow_range()