STK++ 0.9.13
MersenneTwister.h
Go to the documentation of this file.
1// MersenneTwister.h
2// Mersenne Twister random number generator -- a C++ class MTRand
3// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
4// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
5
6// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
7// Copyright (C) 2000 - 2003, Richard J. Wagner
8// Copyright (C) 2005 - 2008, Serge Iovleff
9// All rights reserved.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions
13// are met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in
20// the documentation and/or other materials provided with the
21// distribution.
22//
23// 3. The names of its contributors may not be used to endorse or
24// promote products derived from this software without specific prior
25// written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39// The original code included the following notice:
40//
41// When you use this, send an email to: matumoto@math.keio.ac.jp
42// with an appropriate reference to your work.
43//
44// It would be nice to CC: rjwagner@writeme.com
45// and Cokus@math.washington.edu
46// when you write.
47//
48// Also it would be nice to cc to S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
49// if you are using this code.
50//
51#ifndef MERSENNETWISTER_H
52#define MERSENNETWISTER_H
53
54//#include <iostream>
55#include <limits.h>
56#include <stdio.h>
57#include <time.h>
58#include <math.h>
59
60#include "Analysis/include/STK_Const_Math.h" // for _2PI_
61
87class MTRand
88{
89 // Data
90 public:
92 typedef unsigned long uint32;
93
94 enum { N = 624 };
95 enum { SAVE = N + 1 };
96
97 protected:
98 enum { M = 397 };
99
102 int left;
103
104 //Methods
105 public:
107 inline MTRand( const uint32& oneSeed )
108 { seed(oneSeed); }
109
111 inline MTRand( uint32 *const bigSeed, uint32 const seedLength = N )
112 { seed(bigSeed,seedLength); }
113
115 inline MTRand()
116 { seed(); }
117
119 inline double rand() { return double(randInt()) * (1.0/4294967295.0); }
121 inline double rand( const double& n ) { return rand() * n; }
123 inline double randExc() { return double(randInt()) * (1.0/4294967296.0); }
125 inline double randExc( const double& n ) { return randExc() * n; }
127 inline double randDblExc() { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
129 inline double randDblExc( const double& n ) { return randDblExc() * n; }
130
133 {
134 // Pull a 32-bit integer from the generator state
135 // Every other access function simply transforms the numbers
136 // extracted here
137 if( left == 0 ) reload();
138 --left;
139
140 uint32 s1;
141 s1 = *pNext++;
142 s1 ^= (s1 >> 11);
143 s1 ^= (s1 << 7) & 0x9d2c5680UL;
144 s1 ^= (s1 << 15) & 0xefc60000UL;
145 return ( s1 ^ (s1 >> 18) );
146 }
148 inline double operator()() { return rand(); }
149
151 inline uint32 randInt( const uint32& n )
152 {
153 // Find which bits are used in n
154 // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
155 uint32 used = n;
156 used |= used >> 1;
157 used |= used >> 2;
158 used |= used >> 4;
159 used |= used >> 8;
160 used |= used >> 16;
161
162 // Draw numbers until one is found in [0,n]
163 uint32 i;
164 do
165 i = randInt() & used; // toss unused bits to shorten search
166 while( i > n );
167 return i;
168 }
169
174 inline double rand53()
175 {
176 uint32 a = randInt() >> 5, b = randInt() >> 6;
177 // by Isaku Wada
178 return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0);
179 }
180
184 inline double randNorm( const double& mean, const double& variance )
185 {
186 double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
187 double phi = STK::Const::_2PI_ * randExc();
188 return mean + r * cos(phi);
189 }
190
193 inline void seed( const uint32 oneSeed )
194 {
195 initialize(oneSeed);
196 reload();
197 }
198
207 inline void seed( uint32 *const bigSeed, const uint32 seedLength )
208 {
209 initialize(19650218UL);
210 int i = 1;
211 uint32 j = 0;
212 int k = ( N > seedLength ? N : seedLength );
213 for( ; k; --k )
214 {
215 state[i] =
216 state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
217 state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
218 state[i] &= 0xffffffffUL;
219 ++i; ++j;
220 if( i >= N ) { state[0] = state[N-1]; i = 1; }
221 if( j >= seedLength ) j = 0;
222 }
223 for( k = N - 1; k; --k )
224 {
225 state[i] =
226 state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
227 state[i] -= i;
228 state[i] &= 0xffffffffUL;
229 ++i;
230 if( i >= N ) { state[0] = state[N-1]; i = 1; }
231 }
232 state[0] = 0x80000000UL;// MSB is 1, assuring non-zero initial array
233 reload();
234 }
235
240 inline void seed()
241 {
242 // First try getting an array from /dev/urandom
243 FILE* urandom = fopen( "/dev/urandom", "rb" );
244 if( urandom )
245 {
246 uint32 bigSeed[N];
247 uint32 *s = bigSeed;
248 int i = N;
249 bool success = true;
250 while( success && i-- )
251 success = fread( s++, sizeof(uint32), 1, urandom );
252 fclose(urandom);
253 if( success ) { seed( bigSeed, N ); return; }
254 }
255
256 // Was not successful, so use time() and clock() instead
257 seed( hash( time(NULL), clock() ) );
258 }
259
263 inline void save( uint32* saveArray ) const
264 {
265 uint32 *sa = saveArray;
266 const uint32 *s = state;
267 int i = N;
268 for( ; i--; *sa++ = *s++ ) {}
269 *sa = left;
270 }
271
275 inline void load( uint32 *const loadArray )
276 {
277 uint32 *s = state;
278 uint32 *la = loadArray;
279 int i = N;
280 for( ; i--; *s++ = *la++ ) {}
281 left = *la;
282 pNext = &state[N-left];
283 }
284
285 protected:
292 inline void initialize( const uint32 seed )
293 {
294 uint32 *s = state;
295 uint32 *r = state;
296 int i = 1;
297 *s++ = seed & 0xffffffffUL;
298 for( ; i < N; ++i )
299 {
300 *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
301 r++;
302 }
303 }
304
309 inline void reload()
310 {
311 uint32 *p = state;
312 int i;
313 for( i = N - M; i--; ++p )
314 *p = twist( p[M], p[0], p[1] );
315 for( i = M; --i; ++p )
316 *p = twist( p[M-N], p[0], p[1] );
317 *p = twist( p[M-N], p[0], state[0] );
318
319 left = N, pNext = state;
320 }
322 inline uint32 hiBit( const uint32& u ) const
323 { return u & 0x80000000UL; }
324
326 inline uint32 loBit( const uint32& u ) const
327 { return u & 0x00000001UL; }
328
330 inline uint32 loBits( const uint32& u ) const
331 { return u & 0x7fffffffUL; }
332
334 inline uint32 mixBits( const uint32& u, const uint32& v ) const
335 { return hiBit(u) | loBits(v); }
336
338 inline uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
339 { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
340
345 static inline uint32 hash( time_t t, clock_t c )
346 {
347 static uint32 differ = 0; // guarantee time-based seeds will change
348
349 uint32 h1 = 0;
350 unsigned char *p = (unsigned char *) &t;
351 for( size_t i = 0; i < sizeof(t); ++i )
352 {
353 h1 *= UCHAR_MAX + 2U;
354 h1 += p[i];
355 }
356 uint32 h2 = 0;
357 p = (unsigned char *) &c;
358 for( size_t j = 0; j < sizeof(c); ++j )
359 {
360 h2 *= UCHAR_MAX + 2U;
361 h2 += p[j];
362 }
363 return ( h1 + differ++ ) ^ h2;
364 }
365};
366
367#endif // MERSENNETWISTER_H
In this file we give the main mathematical constants.
Generate unsigner 32 bits random number using the Merdsenne Twister Algorithm.
double rand53()
Access to 53-bit random numbers (capacity of IEEE double precision).
uint32 loBits(const uint32 &u) const
low bits.
void reload()
Generate N new values in state Made disposeer and faster by Matthew Bellew (matthew....
void seed(const uint32 oneSeed)
Re-seeding functions with same behavior as initializers.
MTRand()
auto-initialize with /dev/urandom or time() and clock()
double randExc(const double &n)
real number in [0,n)
uint32 * pNext
Next value to get from state.
uint32 state[N]
internal state
MTRand(uint32 *const bigSeed, uint32 const seedLength=N)
Initialize with a an array.
static uint32 hash(time_t t, clock_t c)
Get a uint32 from t and c Better than uint32(x) in case x is floating point in [0,...
uint32 mixBits(const uint32 &u, const uint32 &v) const
mixed bits.
unsigned long uint32
unsigned integer type, at least 32 bits
double randDblExc()
real number in (0,1)
double randDblExc(const double &n)
real number in (0,n)
uint32 randInt(const uint32 &n)
integer in [0,n] for n < 2^32
uint32 loBit(const uint32 &u) const
low bit.
void seed(uint32 *const bigSeed, const uint32 seedLength)
Re-seeding functions with same behavior as initializers.
double rand()
real number in [0,1]
double rand(const double &n)
real number in [0,n]
void load(uint32 *const loadArray)
Saving and loading generator state.
uint32 randInt()
integer in [0,2^32-1]
uint32 hiBit(const uint32 &u) const
High bit.
int left
number of values left before reload needed
void save(uint32 *saveArray) const
Saving and loading generator state.
MTRand(const uint32 &oneSeed)
Initialize with a simple uint32.
double operator()()
same as rand().
double randNorm(const double &mean, const double &variance)
Access to nonuniform random number distributions.
void seed()
Re-seeding functions with same behavior as initializers.
void initialize(const uint32 seed)
Initialize generator state with seed See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
uint32 twist(const uint32 &m, const uint32 &s0, const uint32 &s1) const
twisted values.
double randExc()
real number in [0,1)