Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | Related Pages | Search for

# eoRNG.h

    00001
    00024 #ifndef EO_RANDOM_NUMBER_GENERATOR
    00025 #define EO_RANDOM_NUMBER_GENERATOR
    00026
    00027 // uint32_t is an unsigned integer type capable of holding 32 bits.
    00028 //
    00029 // In the applicatione here exactly 32 but should typically be fastest, but 64
    00030 // might be better on an Alpha with GCC at -O3 optimization so try your options
    00031 // and see what's best for you.
    00032 //
    00033 // The C99-standard defines uint32_t to be declared in stdint.h, but some
    00034 // systmes don't have that and implement it in inttypes.h.
    00035 #if (! defined __sun)
    00036 #include <stdint.h>
    00037 #else
    00038 #include <inttypes.h>
    00039 #endif
    00040
    00041 #include <vector>
    00042 #include "eoPersistent.h"
    00043 #include "eoObject.h"
    00044
    00103 class eoRng : public eoObject, public eoPersistent
    00104 {
    00105 public :
    00106
    00113     eoRng(uint32_t s)
    00114         : state(0), next(0), left(-1), cached(false), N(624), M(397), K(0x9908B0DFU)
    00115         {
    00116             state = new uint32_t[N+1];
    00117             initialize(2*s);
    00118         }
    00119
    00120     ~eoRng(void)
    00121         {
    00122             delete [] state;
    00123         }
    00124
    00135     void reseed(uint32_t s)
    00136         {
    00137             initialize(2*s);
    00138         }
    00139
    00150     void oldReseed(uint32_t s)
    00151         {
    00152             initialize(s);
    00153         }
    00154
    00158     double uniform(double m = 1.0)
    00159         { // random number between [0, m]
    00160             return m * double(rand()) / double(1.0 + rand_max());
    00161         }
    00162
    00166     uint32_t random(uint32_t m)
    00167         {
    00168             return uint32_t(uniform() * double(m));
    00169         }
    00170
    00175     bool flip(float bias=0.5)
    00176         {
    00177             return uniform() < bias;
    00178         }
    00179
    00183     double normal(void);        // gaussian mutation, stdev 1
    00184
    00188     double normal(double stdev)
    00189         {
    00190             return stdev * normal();
    00191         }
    00192
    00196     double normal(double mean, double stdev)
    00197         {
    00198             return mean + normal(stdev);
    00199         }
    00200
    00204     double negexp(double mean)
    00205         {
    00206             return ( -mean*log((double)rand() / rand_max()));
    00207         }
    00208
    00212     uint32_t rand();
    00213
    00217     uint32_t rand_max(void) const { return uint32_t(0xffffffff); }
    00218
    00224     template <typename TYPE>
    00225     int roulette_wheel(const std::vector<TYPE>& vec, TYPE total = 0)
    00226         {
    00227             if (total == 0)
    00228             { // count
    00229                 for (unsigned    i = 0; i < vec.size(); ++i)
    00230                     total += vec[i];
    00231             }
    00232             double fortune = uniform() * total;
    00233             int i = 0;
    00234             while (fortune > 0)
    00235             {
    00236                 fortune -= vec[i++];
    00237             }
    00238             return --i;
    00239         }
    00240
    00241
    00246     template <typename TYPE>
    00247     const TYPE& choice(const std::vector<TYPE>& vec) const
    00248         { return vec[random(vec.size())]; }
    00249
    00250
    00261     template <typename TYPE>
    00262     TYPE& choice(std::vector<TYPE>& vec)
    00263         { return vec[random(vec.size())]; }
    00264
    00266     void printOn(std::ostream& _os) const
    00267         {
    00268             for (int i = 0; i < N; ++i)
    00269             {
    00270                 _os << state[i] << ' ';
    00271             }
    00272             _os << int(next - state) << ' ';
    00273             _os << left << ' ' << cached << ' ' << cacheValue;
    00274         }
    00275
    00277     void readFrom(std::istream& _is)
    00278         {
    00279             for (int i = 0; i < N; ++i)
    00280             {
    00281                 _is >> state[i];
    00282             }
    00283
    00284             int n;
    00285             _is >> n;
    00286             next = state + n;
    00287
    00288             _is >> left;
    00289             _is >> cached;
    00290             _is >> cacheValue;
    00291         }
    00292
    00293     std::string className(void) const { return "Mersenne-Twister"; }
    00294
    00295 private:
    00296
    00297     uint32_t restart(void);
    00298
    00299
    00300     /* @brief Initialize state
    00301
    00302     We initialize state[0..(N-1)] via the generator
    00303
    00304     <tt>x_new = (69069 * x_old) mod 2^32</tt>
    00305
    00306     from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's _The Art of Computer
    00307     Programming_, Volume 2, 3rd ed.
    00308
    00309     Notes (SJC): I do not know what the initial state requirements of the
    00310     Mersenne Twister are, but it seems this seeding generator could be better.
    00311     It achieves the maximum period for its modulus (2^30) iff x_initial is odd
    00312     (p. 20-21, Sec. 3.2.1.2, Knuth); if x_initial can be even, you have
    00313     sequences like 0, 0, 0, ...; 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...;
    00314     2^29, 2^29 + 2^31, 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd
    00315     below.
    00316
    00317     Even if x_initial is odd, if x_initial is 1 mod 4 then
    00318
    00319     the          lowest bit of x is always 1,
    00320     the  next-to-lowest bit of x is always 0,
    00321     the 2nd-from-lowest bit of x alternates      ... 0 1 0 1 0 1 0 1 ... ,
    00322     the 3rd-from-lowest bit of x 4-cycles        ... 0 1 1 0 0 1 1 0 ... ,
    00323     the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
    00324     ...
    00325
    00326     and if x_initial is 3 mod 4 then
    00327
    00328     the          lowest bit of x is always 1,
    00329     the  next-to-lowest bit of x is always 1,
    00330     the 2nd-from-lowest bit of x alternates      ... 0 1 0 1 0 1 0 1 ... ,
    00331     the 3rd-from-lowest bit of x 4-cycles        ... 0 0 1 1 0 0 1 1 ... ,
    00332     the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
    00333     ...
    00334
    00335     The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is 16,
    00336     which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It also does well
    00337     in the dimension 2..5 spectral tests, but it could be better in dimension 6
    00338     (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
    00339
    00340     Note that the random number user does not see the values generated here
    00341     directly since restart() will always munge them first, so maybe none of all
    00342     of this matters. In fact, the seed values made here could even be
    00343     extra-special desirable if the Mersenne Twister theory says so-- that's why
    00344     the only change I made is to restrict to odd seeds.
    00345     */
    00346     void initialize(uint32_t seed);
    00347
    00349     uint32_t* state;
    00350
    00351     uint32_t* next;
    00352
    00353     int left;
    00354
    00355     // for normal distribution
    00356     bool cached;
    00357
    00358     float cacheValue;
    00359
    00360     const int N;
    00361
    00362     const int M;
    00363
    00365     const uint32_t K;
    00366
    00367
    00376     eoRng(const eoRng&);
    00377
    00382     eoRng& operator=(const eoRng&);
    00383 };
    00384
    00385
    00386
    00387 namespace eo
    00388 {
    00390     extern eoRng rng;
    00391 }
    00392 using eo::rng;
    00393
    00394
    00395
    00396
    00397
    00398 // Implementation of some eoRng members.... Don't mind the mess, it does work.
    00399
    00400
    00401 #define hiBit(u)       ((u) & 0x80000000U)   // mask all but highest   bit of u
    00402 #define loBit(u)       ((u) & 0x00000001U)   // mask all but lowest    bit of u
    00403 #define loBits(u)      ((u) & 0x7FFFFFFFU)   // mask     the highest   bit of u
    00404 #define mixBits(u, v)  (hiBit(u)|loBits(v))  // move hi bit of u to hi bit of v
    00405
    00406 inline void eoRng::initialize(uint32_t seed)
    00407 {
    00408     left = -1;
    00409
    00410     register uint32_t x = (seed | 1U) & 0xFFFFFFFFU, *s = state;
    00411     register int    j;
    00412
    00413     for(left=0, *s++=x, j=N; --j;
    00414         *s++ = (x*=69069U) & 0xFFFFFFFFU);
    00415 }
    00416
    00417
    00418
    00419 inline uint32_t eoRng::restart(void)
    00420 {
    00421     register uint32_t *p0=state, *p2=state+2, *pM=state+M, s0, s1;
    00422     register int    j;
    00423
    00424     left=N-1, next=state+1;
    00425
    00426     for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
    00427         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
    00428
    00429     for(pM=state, j=M; --j; s0=s1, s1=*p2++)
    00430         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
    00431
    00432     s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
    00433     s1 ^= (s1 >> 11);
    00434     s1 ^= (s1 <<  7) & 0x9D2C5680U;
    00435     s1 ^= (s1 << 15) & 0xEFC60000U;
    00436     return(s1 ^ (s1 >> 18));
    00437 }
    00438
    00439
    00440
    00441 inline uint32_t eoRng::rand(void)
    00442 {
    00443
    00444     uint32_t y;
    00445
    00446     if(--left < 0)
    00447         return(restart());
    00448
    00449     y  = *next++;
    00450     y ^= (y >> 11);
    00451     y ^= (y <<  7) & 0x9D2C5680U;
    00452     y ^= (y << 15) & 0xEFC60000U;
    00453     return(y ^ (y >> 18));
    00454 }
    00455
    00456
    00457
    00458 inline double eoRng::normal(void)
    00459 {
    00460     if (cached)
    00461     {
    00462         cached = false;
    00463         return cacheValue;
    00464     }
    00465
    00466     float rSquare, factor, var1, var2;
    00467
    00468     do
    00469     {
    00470         var1 = 2.0 * uniform() - 1.0;
    00471         var2 = 2.0 * uniform() - 1.0;
    00472
    00473         rSquare = var1 * var1 + var2 * var2;
    00474     }
    00475     while (rSquare >= 1.0 || rSquare == 0.0);
    00476
    00477     factor = sqrt(-2.0 * log(rSquare) / rSquare);
    00478
    00479     cacheValue = var1 * factor;
    00480     cached = true;
    00481
    00482     return (var2 * factor);
    00483 }
    00484
    00485
    00486
    00487 namespace eo {
    00488     // a few convenience functions for generating numbers
    00489
    00503     template <typename T>
    00504     inline T random(const T& max) {
    00505         return static_cast<T>(rng.uniform() * max); }
    00506
    00516     template <typename T>
    00517     inline T random(const T& min, const T& max) {
    00518         return static_cast<T>(rng.uniform() * (max-min)) + min; }
    00519
    00521     inline double normal() { return rng.normal(); }
    00522 }
    00523
    00524
    00525 #endif
    00526
    00527
    00528 // Local Variables:
    00529 // coding: iso-8859-1
    00530 // mode: C++
    00531 // c-file-style: "Stroustrup"
    00532 // fill-column: 80
    00533 // End: