2008-02-16 Benjamin Kosnik * include/parallel/random_number.h: Use TR1's mersenne_twister. (random_number::genrand_bits()): Remove. (random_number::set_seed): Remove. Index: include/parallel/random_number.h =================================================================== --- include/parallel/random_number.h (revision 132369) +++ include/parallel/random_number.h (working copy) @@ -39,315 +39,26 @@ #define _GLIBCXX_PARALLEL_RANDOM_NUMBER_H 1 #include +#include namespace __gnu_parallel { - // XXX use tr1 random number. - // http://www.math.keio.ac.jp/matumoto/emt.html - template - class mersenne_twister - { - public: - typedef UIntType result_type; - static const int word_size = w; - static const int state_size = n; - static const int shift_size = m; - static const int mask_bits = r; - static const UIntType parameter_a = a; - static const int output_u = u; - static const int output_s = s; - static const UIntType output_b = b; - static const int output_t = t; - static const UIntType output_c = c; - static const int output_l = l; - - static const bool has_fixed_range = false; - - 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 - { seed(value); } - - template - mersenne_twister(It& first, It last) - { seed(first,last); } - - template - explicit - 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 - { - // New seeding algorithm from - // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html - // In the previous versions, MSBs of the seed affected only MSBs of the - // state x[]. - const UIntType mask = ~0u; - x[0] = value & mask; - for (i = 1; i < n; ++i) - { - // See Knuth "The Art of Computer Programming" Vol. 2, - // 3rd ed., page 106 - x[i] = (1812433253UL * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask; - } - } - - // 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) - { - // I could have used std::generate_n, but it takes "gen" by value - for (int j = 0; j < n; ++j) - x[j] = gen(); - i = n; - } - - template - void - seed(It& first, It last) - { - int j; - for (j = 0; j < n && first != last; ++j, ++first) - x[j] = *first; - i = n; - /* if (first == last && j < n) - throw std::invalid_argument("mersenne_twister::seed");*/ - } - - result_type - min() const - { return 0; } - - result_type - max() const - { - // avoid "left shift count >= with of type" warning - result_type res = 0; - for (int i = 0; i < w; ++i) - res |= (1u << i); - return res; - } - - result_type - operator()(); - - static bool - validation(result_type v) - { return val == v; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - - friend bool - operator==(const mersenne_twister& x, const mersenne_twister& y) - { - for (int j = 0; j < state_size; ++j) - if (x.compute(j) != y.compute(j)) - return false; - return true; - } - - friend bool - operator!=(const mersenne_twister& x, const mersenne_twister& y) - { return !(x == y); } -#else - // Use a member function; Streamable concept not supported. - bool - operator==(const mersenne_twister& rhs) const - { - for (int j = 0; j < state_size; ++j) - if (compute(j) != rhs.compute(j)) - return false; - return true; - } - - bool - operator!=(const mersenne_twister& rhs) const - { return !(*this == rhs); } -#endif - - private: - // returns x(i-n+index), where index is in 0..n-1 - UIntType - compute(unsigned int index) const - { - // equivalent to (i-n+index) % 2n, but doesn't produce negative numbers - return x[ (i + n + index) % (2*n) ]; - } - - void - twist(int block); - - // state representation: next output is o(x(i)) - // x[0] ... x[k] x[k+1] ... x[n-1] x[n] ... x[2*n-1] represents - // x(i-k) ... x(i) x(i+1) ... x(i-k+n-1) x(i-k-n) ... x[i(i-k-1)] - // The goal is to always have x(i-n) ... x(i-1) available for - // operator== and save/restore. - - UIntType x[2*n]; - int i; - }; - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION - // A definition is required even for integral static constants - template - const bool - mersenne_twister::has_fixed_range; - - template - const int - mersenne_twister::state_size; - - template - const int - mersenne_twister::shift_size; - - template - const int - mersenne_twister::mask_bits; - - template - const UIntType - mersenne_twister::parameter_a; - - template - const int - mersenne_twister::output_u; - - template - const int - mersenne_twister::output_s; - - template - const UIntType - mersenne_twister::output_b; - - template - const int - mersenne_twister::output_t; - - template - const UIntType - mersenne_twister::output_c; - - template - const int - mersenne_twister::output_l; -#endif - - template - void - mersenne_twister::twist(int block) - { - const UIntType upper_mask = (~0u) << r; - const UIntType lower_mask = ~upper_mask; - - if (block == 0) - { - for (int j = n; j < 2*n; ++j) - { - UIntType y = (x[j-n] & upper_mask) | (x[j-(n-1)] & lower_mask); - x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0); - } - } - else if (block == 1) - { - // split loop to avoid costly modulo operations - { // extra scope for MSVC brokenness w.r.t. for scope - for (int j = 0; j < n-m; ++j) - { - UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask); - x[j] = x[j+n+m] ^ (y >> 1) ^ (y&1 ? a : 0); - } - } - - for (int j = n-m; j < n-1; ++j) - { - UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask); - x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0); - } - // last iteration - UIntType y = (x[2*n-1] & upper_mask) | (x[0] & lower_mask); - x[n-1] = x[m-1] ^ (y >> 1) ^ (y&1 ? a : 0); - i = 0; - } - } - - template - inline - typename mersenne_twister::result_type - mersenne_twister::operator()() - { - if (i == n) - twist(0); - else if (i >= 2*n) - twist(1); - // Step 4 - UIntType z = x[i]; - ++i; - z ^= (z >> u); - z ^= ((z << s) & b); - z ^= ((z << t) & c); - z ^= (z >> l); - return z; - } - - - typedef mersenne_twister mt11213b; - - // validation by experiment from mt19937.c - typedef mersenne_twister mt19937; - /** @brief Random number generator, based on the Mersenne twister. */ class random_number { private: - mt19937 mt; - uint64_t supremum, RAND_SUP; - double supremum_reciprocal, RAND_SUP_REC; + std::tr1::mt19937 mt; + uint64_t supremum; + uint64_t RAND_SUP; + double supremum_reciprocal; + double RAND_SUP_REC; - uint64_t cache; /* assumed to be twice as long as the usual random number */ - int bits_left; /* bit results */ + // Assumed to be twice as long as the usual random number. + uint64_t cache; + // Bit results. + int bits_left; + static uint32_t scale_down(uint64_t x, #if _GLIBCXX_SCALE_DOWN_FPU @@ -357,7 +68,7 @@ #endif { #if _GLIBCXX_SCALE_DOWN_FPU - return (uint32_t)(x * supremum_reciprocal); + return uint32_t(x * supremum_reciprocal); #else return static_cast(x % supremum); #endif @@ -368,8 +79,8 @@ random_number() : mt(0), supremum(0x100000000ULL), RAND_SUP(1ULL << (sizeof(uint32_t) * 8)), - supremum_reciprocal((double)supremum / (double)RAND_SUP), - RAND_SUP_REC(1.0 / (double)RAND_SUP), + supremum_reciprocal(double(supremum) / double(RAND_SUP)), + RAND_SUP_REC(1.0 / double(RAND_SUP)), cache(0), bits_left(0) { } /** @brief Constructor. @@ -379,8 +90,8 @@ random_number(uint32_t seed, uint64_t supremum = 0x100000000ULL) : mt(seed), supremum(supremum), RAND_SUP(1ULL << (sizeof(uint32_t) * 8)), - supremum_reciprocal((double)supremum / (double)RAND_SUP), - RAND_SUP_REC(1.0 / (double)RAND_SUP), + supremum_reciprocal(double(supremum) / double(RAND_SUP)), + RAND_SUP_REC(1.0 / double(RAND_SUP)), cache(0), bits_left(0) { } /** @brief Generate unsigned random 32-bit integer. */ @@ -394,35 +105,9 @@ operator()(uint64_t local_supremum) { return scale_down(mt(), local_supremum, - (double)local_supremum * RAND_SUP_REC); + double(local_supremum * RAND_SUP_REC)); } - /** @brief Set the random seed. - * @param seed to set. */ - void - set_seed(uint32_t seed) - { - mt.seed(seed); - cache = mt(); - bits_left = 32; - } - - /** @brief Generate a number of random bits, compile-time parameter. */ - template - unsigned long - genrand_bits() - { - unsigned long res = cache & ((1 << bits) - 1); - cache = cache >> bits; - bits_left -= bits; - if (bits_left < 32) - { - cache |= (((uint64_t)mt()) << bits_left); - bits_left += 32; - } - return res; - } - /** @brief Generate a number of random bits, run-time parameter. * @param bits Number of bits to generate. */ unsigned long @@ -433,7 +118,7 @@ bits_left -= bits; if (bits_left < 32) { - cache |= (((uint64_t)mt()) << bits_left); + cache |= ((uint64_t(mt())) << bits_left); bits_left += 32; } return res;