Index: boost/random/linear_feedback_shift.hpp =================================================================== --- boost/random/linear_feedback_shift.hpp (revision 57432) +++ boost/random/linear_feedback_shift.hpp (working copy) @@ -77,7 +77,12 @@ seed(first, last); } - void seed(UIntType s0 = 341) { assert(s0 >= (1 << (w-k))); value = s0; } + void seed(UIntType s0 = 341) { + if(s0 < (1 << (w-k))) { + s0 += 1 << (w-k); + } + value = s0; + } template void seed(It& first, It last) { if(first == last) Index: boost/random/linear_congruential.hpp =================================================================== --- boost/random/linear_congruential.hpp (revision 57432) +++ boost/random/linear_congruential.hpp (working copy) @@ -54,12 +54,9 @@ // BOOST_STATIC_ASSERT(m == 0 || c < m); explicit linear_congruential(IntType x0 = 1) - : _modulus(modulus), _x(_modulus ? (x0 % _modulus) : x0) + : _modulus(modulus) { - assert(c || x0); /* if c == 0 and x(0) == 0 then x(n) = 0 for all n */ - // overflow check - // disabled because it gives spurious "divide by zero" gcc warnings - // assert(m == 0 || (a*(m-1)+c) % m == (c < a ? c-a+m : c-a)); + seed(x0); // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS @@ -77,8 +74,22 @@ // compiler-generated copy constructor and assignment operator are fine void seed(IntType x0 = 1) { - assert(c || x0); - _x = (_modulus ? (x0 % _modulus) : x0); + // wrap _x if it doesn't fit in the destination + if(modulus == 0) { + _x = x0; + } else { + _x = x0 % modulus; + } + // handle negative seeds + if(_x < 0) { + _x += modulus; + } + // adjust to the correct range + if(increment == 0 && _x == 0) { + _x = 1; + } + assert(_x >= min()); + assert(_x <= max()); } template @@ -86,8 +97,7 @@ { if(first == last) throw std::invalid_argument("linear_congruential::seed"); - IntType value = *first++; - _x = (_modulus ? (value % _modulus) : value); + seed(*first++); } result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return c == 0 ? 1 : 0; } @@ -261,7 +271,7 @@ if(sizeof(T) < sizeof(uint64_t)) { return (static_cast(x) << 16) | 0x330e; } else { - return(static_cast(x)); + return(static_cast(x)); } } static uint64_t cnv(float x) { return(static_cast(x)); } Index: libs/random/random-generators.html =================================================================== --- libs/random/random-generators.html (revision 57432) +++ libs/random/random-generators.html (working copy) @@ -495,11 +495,21 @@

Effects: Constructs a linear_congruential - generator with x(0) := x0.

+ generator, seeding it with x0.

+
 void seed(IntType x0)
 
+ +

Effects: If c mod m is zero + and x0 mod m is zero, changes the current value of + the generator to 1. Otherwise, changes it to x0 mod + m. If c is zero, distinct seeds in the range + [1,m) will leave the generator in distinct states. If c + is not zero, the range is [0,m). +

+

Effects: Changes the current value x(n) of the generator to x0.

@@ -605,8 +615,13 @@ static const result_type min_value = 1; static const result_type max_value = MLCG1::max_value-1; additive_combine(); + additive_combine(typename MLCG1::result_type seed); additive_combine(typename MLCG1::result_type seed1, typename MLCG2::result_type seed2); + void seed(); + void seed(typename MLCG1::result_type seed); + void seed(typename MLCG1::result_type seed1, + typename MLCG2::result_type seed2); result_type operator()(); bool validation(result_type x) const; }; @@ -645,7 +660,16 @@

Effects: Constructs an additive_combine generator using the default constructors of the two base generators.

+
+additive_combine(typename MLCG1::result_type seed)
+
+ +

Effects: Constructs an additive_combine + generator, using seed as the constructor argument for + both base generators.

+ +
 additive_combine(typename MLCG1::result_type seed1, 
                  typename MLCG2::result_type seed2)
 
@@ -655,6 +679,30 @@ constructor argument to the first and second base generator, respectively.

+
+void seed()
+
+ +

Effects: Seeds an additive_combine + generator using the default seeds of the two base generators.

+ +
+void seed(typename MLCG1::result_type seed)
+
+ +

Effects: Seeds an additive_combine + generator, using seed as the seed for both base + generators.

+ +
+void seed(typename MLCG1::result_type seed1, 
+          typename MLCG2::result_type seed2)
+
+ +

Effects: Seeds an additive_combine + generator, using seed1 and seed2 as the + seeds to the first and second base generator, respectively.

+

Specialization

The specialization ecuyer1988 was suggested in the above @@ -997,7 +1045,7 @@

Description

-

Instantiations of class template lagged_fibonacci model a +

Instantiations of class template lagged_fibonacci_01 model a pseudo-random number generator. It uses a lagged Fibonacci algorithm with two lags p and q, evaluated in floating-point arithmetic: x(i) = x(i-p) + x(i-q) (mod 1) with @@ -1050,7 +1098,10 @@

Effects: Constructs a minstd_rand0 generator with the constructor parameter value and calls - seed with it.

+ seed with it. Distinct seeds in the range [1, 2147483647) + will produce generators with different states. Other seeds will be + equivalent to some seed within this range. See + linear_congruential for details.

 template<class Generator> void seed(Generator & gen)
 
Index: libs/random/instantiate.cpp =================================================================== --- libs/random/instantiate.cpp (revision 57432) +++ libs/random/instantiate.cpp (working copy) @@ -133,53 +133,63 @@ 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); +template +void test_seed_conversion(URNG & urng, const T & t, const Converted &) { + Converted c = static_cast(t); + if(static_cast(c) == t) { + URNG urng2(c); + BOOST_CHECK_MESSAGE(urng == urng2, std::string("Testing seed constructor: ") + typeid(Converted).name()); + urng2.seed(c); + BOOST_CHECK(urng == urng2); + } } // rand48 uses non-standard seeding -template -void test_seed(boost::rand48 & urng, const T & t) { +template +void test_seed_conversion(boost::rand48 & urng, const T & t, const Converted &) { boost::rand48 urng2(t); urng2.seed(t); } template -void instantiate_seed(const URNG &, const ResultType &) { +void test_seed(const URNG &, const ResultType & v) { + typename URNG::result_type value = static_cast(v); + + URNG urng(value); + + // integral types + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); +#if !defined(BOOST_NO_INT64_T) + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); +#endif + + // floating point types + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); + test_seed_conversion(urng, value, static_cast(0)); +} + +template +void instantiate_seed(const URNG & 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)); - } + test_seed(urng, 0); + test_seed(urng, 127); + test_seed(urng, 539157235); + test_seed(urng, ~0u); } template