EvolvingObjects
eoRNG.h
00001 
00025 #ifndef EO_RANDOM_NUMBER_GENERATOR
00026 #define EO_RANDOM_NUMBER_GENERATOR
00027 
00032 # if (defined _MSC_VER)
00033 
00040 typedef unsigned long uint32_t;
00041 #else
00042 #if (! defined __sun)
00043 // The C99-standard defines uint32_t to be declared in stdint.h, but some
00044 // systems don't have that and implement it in inttypes.h.
00045 #include <stdint.h>
00046 #else
00047 #include <inttypes.h>
00048 #endif
00049 #endif
00050 
00051 #include <cmath>
00052 #include <vector>
00053 #include "eoPersistent.h"
00054 #include "eoObject.h"
00055 
00056 
00115 class eoRng : public eoObject, public eoPersistent
00116 {
00117 public :
00118 
00125     eoRng(uint32_t s)
00126         : state(0), next(0), left(-1), cached(false)
00127         {
00128             state = new uint32_t[N+1];
00129             initialize(2*s);
00130         }
00131 
00133     ~eoRng()
00134         {
00135             delete [] state;
00136         }
00137 
00148     void reseed(uint32_t s)
00149         {
00150             initialize(2*s);
00151         }
00152 
00153     /* FIXME remove in next release
00154     ** Re-initializes the Random Number Generator
00155 
00156     This is the traditional seeding procedure. This version is deprecated and
00157     only provided for compatibility with old code. In new projects you should
00158     use reseed.
00159 
00160     @see reseed for details on usage of the seeding value.
00161 
00162     @version old version (deprecated)
00163     *
00164     void oldReseed(uint32_t s)
00165         {
00166             initialize(s);
00167         }
00168     */
00169 
00175     double uniform(double m = 1.0)
00176         { // random number between [0, m]
00177             return m * double(rand()) / double(1.0 + rand_max());
00178         }
00179 
00186     double uniform(double min, double max)
00187         { // random number between [min, max]
00188             return min + uniform(max - min);
00189         }
00190 
00196     uint32_t random(uint32_t m)
00197         {
00198             // C++ Standard (4.9 Floatingintegral conversions [conv.fpint])
00199             // defines floating point to integer conversion as truncation
00200             // ("rounding towards zero"): "An rvalue of a floating point type
00201             // can be converted to an rvalue of an integer type. The conversion
00202             // truncates; that is, the fractional part is discarded"
00203             return uint32_t(uniform() * double(m));
00204         }
00205 
00213     bool flip(double bias=0.5)
00214         {
00215             return uniform() < bias;
00216         }
00217 
00225     double normal();
00226 
00234     double normal(double stdev)
00235         { return stdev * normal(); }
00236 
00245     double normal(double mean, double stdev)
00246         { return mean + normal(stdev); }
00247 
00253     double negexp(double mean)
00254         {
00255             return -mean*log(double(rand()) / rand_max());
00256         }
00257 
00261     uint32_t rand();
00262 
00266     uint32_t rand_max() const { return uint32_t(0xffffffff); }
00267 
00274     template <typename TYPE>
00275     int roulette_wheel(const std::vector<TYPE>& vec, TYPE total = 0)
00276         {
00277             if (total == 0)
00278             { // count
00279                 for (unsigned    i = 0; i < vec.size(); ++i)
00280                     total += vec[i];
00281             }
00282             double fortune = uniform() * total;
00283             int i = 0;
00284             while (fortune >= 0)
00285             {
00286                 fortune -= vec[i++];
00287             }
00288             return --i;
00289         }
00290 
00291 
00296     template <typename TYPE>
00297     const TYPE& choice(const std::vector<TYPE>& vec)
00298         { return vec[random(vec.size())]; }
00299 
00300 
00311     template <typename TYPE>
00312     TYPE& choice(std::vector<TYPE>& vec)
00313         { return vec[random(vec.size())]; }
00314 
00319     void printOn(std::ostream& _os) const
00320         {
00321             for (int i = 0; i < N; ++i)
00322             {
00323                 _os << state[i] << ' ';
00324             }
00325             _os << int(next - state) << ' ';
00326             _os << left << ' ' << cached << ' ' << cacheValue;
00327         }
00328 
00333     void readFrom(std::istream& _is)
00334         {
00335             for (int i = 0; i < N; ++i)
00336             {
00337                 _is >> state[i];
00338             }
00339 
00340             int n;
00341             _is >> n;
00342             next = state + n;
00343 
00344             _is >> left;
00345             _is >> cached;
00346             _is >> cacheValue;
00347         }
00348 
00349     std::string className() const { return "Mersenne-Twister"; }
00350 
00351 private:
00352 
00353     uint32_t restart();
00354 
00355     /* @brief Initialize state
00356 
00357     We initialize state[0..(N-1)] via the generator
00358 
00359     <tt>x_new = (69069 * x_old) mod 2^32</tt>
00360 
00361     from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's _The Art of Computer
00362     Programming_, Volume 2, 3rd ed.
00363 
00364     Notes (SJC): I do not know what the initial state requirements of the
00365     Mersenne Twister are, but it seems this seeding generator could be better.
00366     It achieves the maximum period for its modulus (2^30) iff x_initial is odd
00367     (p. 20-21, Sec. 3.2.1.2, Knuth); if x_initial can be even, you have
00368     sequences like 0, 0, 0, ...; 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...;
00369     2^29, 2^29 + 2^31, 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd
00370     below.
00371 
00372     Even if x_initial is odd, if x_initial is 1 mod 4 then
00373 
00374     the          lowest bit of x is always 1,
00375     the  next-to-lowest bit of x is always 0,
00376     the 2nd-from-lowest bit of x alternates      ... 0 1 0 1 0 1 0 1 ... ,
00377     the 3rd-from-lowest bit of x 4-cycles        ... 0 1 1 0 0 1 1 0 ... ,
00378     the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
00379     ...
00380 
00381     and if x_initial is 3 mod 4 then
00382 
00383     the          lowest bit of x is always 1,
00384     the  next-to-lowest bit of x is always 1,
00385     the 2nd-from-lowest bit of x alternates      ... 0 1 0 1 0 1 0 1 ... ,
00386     the 3rd-from-lowest bit of x 4-cycles        ... 0 0 1 1 0 0 1 1 ... ,
00387     the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
00388     ...
00389 
00390     The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is 16,
00391     which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It also does well
00392     in the dimension 2..5 spectral tests, but it could be better in dimension 6
00393     (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
00394 
00395     Note that the random number user does not see the values generated here
00396     directly since restart() will always munge them first, so maybe none of all
00397     of this matters. In fact, the seed values made here could even be
00398     extra-special desirable if the Mersenne Twister theory says so-- that's why
00399     the only change I made is to restrict to odd seeds.
00400     */
00401     void initialize(uint32_t seed);
00402 
00404     uint32_t *state;
00405 
00407     uint32_t *next;
00408 
00410     int left;
00411 
00413     bool cached;
00414 
00416     double cacheValue;
00417 
00419     static const int N;
00420 
00422     static const int M;
00423 
00425     static const uint32_t K;
00426 
00427 
00436     eoRng(const eoRng&);
00437 
00442     eoRng& operator=(const eoRng&);
00443 };
00449 namespace eo
00450 {
00452     extern eoRng rng;
00453 }
00454 using eo::rng;
00455 
00461 // Implementation of some eoRng members.... Don't mind the mess, it does work.
00462 
00463 #define hiBit(u)       ((u) & 0x80000000U)   // mask all but highest   bit of u
00464 #define loBit(u)       ((u) & 0x00000001U)   // mask all but lowest    bit of u
00465 #define loBits(u)      ((u) & 0x7FFFFFFFU)   // mask     the highest   bit of u
00466 #define mixBits(u, v)  (hiBit(u)|loBits(v))  // move hi bit of u to hi bit of v
00467 
00468 
00469 inline void eoRng::initialize(uint32_t seed)
00470 {
00471     left = -1;
00472 
00473     register uint32_t x = (seed | 1U) & 0xFFFFFFFFU, *s = state;
00474     register int j;
00475 
00476     for(left=0, *s++=x, j=N; --j;
00477         *s++ = (x*=69069U) & 0xFFFFFFFFU) ;
00478 }
00479 
00480 
00481 
00482 inline uint32_t eoRng::restart()
00483 {
00484     register uint32_t *p0=state, *p2=state+2, *pM=state+M, s0, s1;
00485     register int j;
00486 
00487     left=N-1, next=state+1;
00488 
00489     for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
00490         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
00491 
00492     for(pM=state, j=M; --j; s0=s1, s1=*p2++)
00493         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
00494 
00495     s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
00496     s1 ^= (s1 >> 11);
00497     s1 ^= (s1 <<  7) & 0x9D2C5680U;
00498     s1 ^= (s1 << 15) & 0xEFC60000U;
00499     return(s1 ^ (s1 >> 18));
00500 }
00501 
00502 
00503 
00504 inline uint32_t eoRng::rand()
00505 {
00506     if(--left < 0)
00507         return(restart());
00508     uint32_t y  = *next++;
00509     y ^= (y >> 11);
00510     y ^= (y <<  7) & 0x9D2C5680U;
00511     y ^= (y << 15) & 0xEFC60000U;
00512     return(y ^ (y >> 18));
00513 }
00514 
00515 
00516 
00517 inline double eoRng::normal()
00518 {
00519     if (cached) {
00520         cached = false;
00521         return cacheValue;
00522     }
00523     double rSquare, var1, var2;
00524     do {
00525         var1 = 2.0 * uniform() - 1.0;
00526         var2 = 2.0 * uniform() - 1.0;
00527         rSquare = var1 * var1 + var2 * var2;
00528     } while (rSquare >= 1.0 || rSquare == 0.0);
00529     double factor = sqrt(-2.0 * log(rSquare) / rSquare);
00530     cacheValue = var1 * factor;
00531     cached = true;
00532     return (var2 * factor);
00533 }
00534 
00535 
00536 
00537 namespace eo
00538 {
00555     template <typename T>
00556     inline T random(const T& min, const T& max) {
00557         return static_cast<T>(rng.uniform() * (max-min)) + min; }
00558 
00576     template <typename T>
00577     inline T random(const T& max) {
00578         return static_cast<T>(rng.uniform() * max); }
00579 
00587     inline double normal() { return rng.normal(); }
00588 }
00589 
00590 
00591 #endif
00592 
00593 
00594 // Local Variables:
00595 // coding: iso-8859-1
00596 // mode: C++
00597 // c-file-offsets: ((c . 0))
00598 // c-file-style: "Stroustrup"
00599 // fill-column: 80
00600 // End:
 All Classes Namespaces Files Functions Variables Typedefs Friends