2 //////////////////////////////////////////////////////////////////////////////
3 // This file includes code derived from the original Mersenne Twister Code
4 // by Makoto Matsumoto and Takuji Nishimura
5 // and is subject to their original copyright notice copied below:
6 //////////////////////////////////////////////////////////////////////////////
8 //////////////////////////////////////////////////////////////////////////////
9 // COPYRIGHT NOTICE FOR MERSENNE TWISTER CODE
10 // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
11 // All rights reserved.
13 // Redistribution and use in source and binary forms, with or without
14 // modification, are permitted provided that the following conditions
17 // 1. Redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
20 // 2. Redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
24 // 3. The names of its contributors may not be used to endorse or promote
25 // products derived from this software without specific prior written
28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 ///////////////////////////////////////////////////////////////////////////////
43 #include "MathConstant.h"
48 //Constants used internally by Mersenne random number generator
49 #define MERSENNE_N 624
50 #define MERSENNE_M 397
53 #define MATRIX_A 0x9908b0dfUL
55 // most significant w-r bits
56 #define UPPER_MASK 0x80000000UL
58 // least significant r bits
59 #define LOWER_MASK 0x7fffffffUL
62 // Constants used internally by Park-Miller random generator
69 #define NDIV (1+(IM-1)/NTAB)
70 #define RNMX (1.0-EPS)
72 Random::Random(long s)
75 mt = new unsigned long [MERSENNE_N];
77 mersenneMult = 1.0/4294967296.0;
79 shuffler = new long [NTAB];
93 void Random::Reset(long s)
100 // 'Continuous' Random Generator
102 seed = s == 0 ? 1 : -s; // seed == 0 would be disastrous
104 for (int j=NTAB+7; j>=0; j--) // Warm up and set shuffle table
107 seed = IA * (seed - k * IQ) - IR * k;
108 if (seed < 0) seed += IM;
109 if (j < NTAB) shuffler[j] = seed;
115 // initializes mt[MERSENNE_N] with a seed
116 void Random::InitMersenne(unsigned long s)
118 mt[0]= s & 0xffffffffUL;
119 for (mti = 1; mti < MERSENNE_N; mti++)
121 mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
122 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
123 /* In the previous versions, MSBs of the seed affect */
124 /* only MSBs of the array mt[]. */
125 /* 2002/01/09 modified by Makoto Matsumoto */
127 mt[mti] &= 0xffffffffUL;
133 return Next() > 0.5 ? 1 : 0;
136 #ifndef __NO_MERSENNE
138 double Random::Next()
142 // mag01[x] = x * MATRIX_A for x=0,1
143 static unsigned long mag01[2]={0x0UL, MATRIX_A};
145 if (mti >= MERSENNE_N)
147 /* generate MERSENNE_N words at one time */
150 // If InitMersenne() has not been called, a default initial seed is used
151 if (mti == MERSENNE_N+1)
152 InitMersenne(5489UL);
154 for (kk=0; kk < MERSENNE_N-MERSENNE_M; kk++)
156 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
157 mt[kk] = mt[kk+MERSENNE_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
160 for (; kk < MERSENNE_N-1; kk++)
162 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
163 mt[kk] = mt[kk+(MERSENNE_M - MERSENNE_N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
166 y = (mt[MERSENNE_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
167 mt[MERSENNE_N-1] = mt[MERSENNE_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
176 y ^= (y << 7) & 0x9d2c5680UL;
177 y ^= (y << 15) & 0xefc60000UL;
180 return (mersenneMult * ((double) y + 0.5));
183 // Generates a random number on [0,0xffffffff]-interval
185 unsigned long Random::NextInt()
189 // mag01[x] = x * MATRIX_A for x=0,1
190 static unsigned long mag01[2]={0x0UL, MATRIX_A};
192 if (mti >= MERSENNE_N)
194 /* generate MERSENNE_N words at one time */
197 // If InitMersenne() has not been called, a default initial seed is used
198 if (mti == MERSENNE_N + 1)
199 InitMersenne(5489UL);
201 for (kk= 0; kk < MERSENNE_N - MERSENNE_M; kk++)
203 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
204 mt[kk] = mt[kk+MERSENNE_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
207 for (; kk< MERSENNE_N-1; kk++)
209 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
210 mt[kk] = mt[kk+(MERSENNE_M - MERSENNE_N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
213 y = (mt[MERSENNE_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
214 mt[MERSENNE_N-1] = mt[MERSENNE_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
223 y ^= (y << 7) & 0x9d2c5680UL;
224 y ^= (y << 15) & 0xefc60000UL;
232 double Random::Next()
234 // Compute seed = (IA * seed) % IM without overflows
235 // by Schrage's method
237 seed = IA * (seed - k * IQ) - IR * k;
238 if (seed < 0) seed += IM;
243 // Output value is shuffler[j], which is in turn replaced by seed
247 // Map to 0.0 .. 1.0 excluding endpoints
248 double temp = AM * last;
249 if (temp > RNMX) return RNMX;
253 unsigned long Random::NextInt()
255 // Compute seed = (IA * seed) % IM without overflows
256 // by Schrage's method
258 seed = IA * (seed - k * IQ) - IR * k;
259 if (seed < 0) seed += IM;
264 // Output value is shuffler[j], which is in turn replaced by seed
273 double Random::Normal()
275 double v1, v2, fac, rsq;
277 if (!normSaved) // Do we need new numbers?
280 v1 = 2.0 * Next() - 1.0; // Pick two coordinates from
281 v2 = 2.0 * Next() - 1.0; // -1 to +1 and check if they
282 rsq = v1*v1 + v2*v2; // are in unit circle...
283 } while (rsq >= 1.0 || rsq == 0.0);
285 fac = sqrt(-2.0 * log(rsq)/rsq); // Apply the Box-Muller
286 normStore = v1 * fac; // transformation and save
287 normSaved = 1; // one deviate for next time
297 void Random::Choose(int * array, int n, int k)
299 int choices = 1, others = 0;
308 for (int i = 0; i < n; i++)
313 int i = NextInt() % n;
315 if (array[i] == choices) continue;
322 void Random::Choose(int * array, float * weights, int n, int k)
324 int choices = 1, others = 0;
333 // First calculate cumulative sums of weights ...
334 float * cumulative = new float [n + 1];
337 for (int i = 1; i <= n; i++)
338 cumulative[i] = cumulative[i - 1] + weights[i - 1];
340 float & sum = cumulative[n], reject = 0.0;
342 for (int i = 0; i < n; i++)
347 float weight = (float)(Next() * sum);
349 int hi = n, lo = 0, i = 0;
355 if (cumulative[i + 1] <= weight)
357 else if (cumulative[i] >= weight)
362 if (array[i] == choices) continue;
365 reject += weights[i];
367 // After selecting a substantial number of elements, update the cumulative
368 // distribution -- to ensure that at least half of our samples produce a hit
369 if (reject > sum * 0.50)
372 for (int i = 1; i <= n; i++)
373 if (array[i] != choices)
374 cumulative[i] = cumulative[i - 1] + weights[i - 1];
376 cumulative[i] = cumulative[i - 1];