libStatGen Software
1
|
00001 /* 00002 * Copyright (C) 2010 Regents of the University of Michigan 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 00019 ////////////////////////////////////////////////////////////////////////////// 00020 // This file includes code derived from the original Mersenne Twister Code 00021 // by Makoto Matsumoto and Takuji Nishimura 00022 // and is subject to their original copyright notice copied below: 00023 ////////////////////////////////////////////////////////////////////////////// 00024 00025 ////////////////////////////////////////////////////////////////////////////// 00026 // COPYRIGHT NOTICE FOR MERSENNE TWISTER CODE 00027 // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 00028 // All rights reserved. 00029 // 00030 // Redistribution and use in source and binary forms, with or without 00031 // modification, are permitted provided that the following conditions 00032 // are met: 00033 // 00034 // 1. Redistributions of source code must retain the above copyright 00035 // notice, this list of conditions and the following disclaimer. 00036 // 00037 // 2. Redistributions in binary form must reproduce the above copyright 00038 // notice, this list of conditions and the following disclaimer in the 00039 // documentation and/or other materials provided with the distribution. 00040 // 00041 // 3. The names of its contributors may not be used to endorse or promote 00042 // products derived from this software without specific prior written 00043 // permission. 00044 // 00045 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00046 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00047 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00048 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00049 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00050 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00051 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00052 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00053 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00054 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00055 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00056 // 00057 /////////////////////////////////////////////////////////////////////////////// 00058 00059 #include "Random.h" 00060 #include "MathConstant.h" 00061 #include "Error.h" 00062 00063 #include <math.h> 00064 00065 //Constants used internally by Mersenne random number generator 00066 #define MERSENNE_N 624 00067 #define MERSENNE_M 397 00068 00069 // constant vector a 00070 #define MATRIX_A 0x9908b0dfUL 00071 00072 // most significant w-r bits 00073 #define UPPER_MASK 0x80000000UL 00074 00075 // least significant r bits 00076 #define LOWER_MASK 0x7fffffffUL 00077 00078 00079 // Constants used internally by Park-Miller random generator 00080 #define IA 16807 00081 #define IM 2147483647 00082 #define AM (1.0 / IM) 00083 #define IQ 127773 00084 #define IR 2836 00085 #define NTAB 32 00086 #define NDIV (1+(IM-1)/NTAB) 00087 #define RNMX (1.0-EPS) 00088 00089 Random::Random(long s) 00090 { 00091 #ifndef __NO_MERSENNE 00092 mt = new unsigned long [MERSENNE_N]; 00093 mti = MERSENNE_N + 1; 00094 mersenneMult = 1.0/4294967296.0; 00095 #else 00096 shuffler = new long [NTAB]; 00097 #endif 00098 Reset(s); 00099 } 00100 00101 Random::~Random() 00102 { 00103 #ifndef __NO_MERSENNE 00104 delete [] mt; 00105 #else 00106 delete [] shuffler; 00107 #endif 00108 } 00109 00110 void Random::Reset(long s) 00111 { 00112 normSaved = 0; 00113 00114 #ifndef __NO_MERSENNE 00115 InitMersenne(s); 00116 #else 00117 // 'Continuous' Random Generator 00118 if ((seed = s) < 1) 00119 seed = s == 0 ? 1 : -s; // seed == 0 would be disastrous 00120 00121 for (int j=NTAB+7; j>=0; j--) // Warm up and set shuffle table 00122 { 00123 long k = seed / IQ; 00124 seed = IA * (seed - k * IQ) - IR * k; 00125 if (seed < 0) seed += IM; 00126 if (j < NTAB) shuffler[j] = seed; 00127 } 00128 last=shuffler[0]; 00129 #endif 00130 } 00131 00132 // initializes mt[MERSENNE_N] with a seed 00133 void Random::InitMersenne(unsigned long s) 00134 { 00135 mt[0]= s & 0xffffffffUL; 00136 for (mti = 1; mti < MERSENNE_N; mti++) 00137 { 00138 mt[mti] = (1812433253UL * (mt[mti-1] ^(mt[mti-1] >> 30)) + mti); 00139 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 00140 /* In the previous versions, MSBs of the seed affect */ 00141 /* only MSBs of the array mt[]. */ 00142 /* 2002/01/09 modified by Makoto Matsumoto */ 00143 00144 mt[mti] &= 0xffffffffUL; 00145 } 00146 } 00147 00148 int Random::Binary() 00149 { 00150 return Next() > 0.5 ? 1 : 0; 00151 } 00152 00153 #ifndef __NO_MERSENNE 00154 00155 double Random::Next() 00156 { 00157 unsigned long y; 00158 00159 // mag01[x] = x * MATRIX_A for x=0,1 00160 static unsigned long mag01[2]={0x0UL, MATRIX_A}; 00161 00162 if (mti >= MERSENNE_N) 00163 { 00164 /* generate MERSENNE_N words at one time */ 00165 int kk; 00166 00167 // If InitMersenne() has not been called, a default initial seed is used 00168 if (mti == MERSENNE_N+1) 00169 InitMersenne(5489UL); 00170 00171 for (kk=0; kk < MERSENNE_N-MERSENNE_M; kk++) 00172 { 00173 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); 00174 mt[kk] = mt[kk+MERSENNE_M] ^(y >> 1) ^ mag01[y & 0x1UL]; 00175 } 00176 00177 for (; kk < MERSENNE_N-1; kk++) 00178 { 00179 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); 00180 mt[kk] = mt[kk+(MERSENNE_M - MERSENNE_N)] ^(y >> 1) ^ mag01[y & 0x1UL]; 00181 } 00182 00183 y = (mt[MERSENNE_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); 00184 mt[MERSENNE_N-1] = mt[MERSENNE_M-1] ^(y >> 1) ^ mag01[y & 0x1UL]; 00185 00186 mti = 0; 00187 } 00188 00189 y = mt[mti++]; 00190 00191 // Tempering 00192 y ^= (y >> 11); 00193 y ^= (y << 7) & 0x9d2c5680UL; 00194 y ^= (y << 15) & 0xefc60000UL; 00195 y ^= (y >> 18); 00196 00197 return (mersenneMult *((double) y + 0.5)); 00198 } 00199 00200 // Generates a random number on [0,0xffffffff]-interval 00201 00202 unsigned long Random::NextInt() 00203 { 00204 unsigned long y; 00205 00206 // mag01[x] = x * MATRIX_A for x=0,1 00207 static unsigned long mag01[2]={0x0UL, MATRIX_A}; 00208 00209 if (mti >= MERSENNE_N) 00210 { 00211 /* generate MERSENNE_N words at one time */ 00212 int kk; 00213 00214 // If InitMersenne() has not been called, a default initial seed is used 00215 if (mti == MERSENNE_N + 1) 00216 InitMersenne(5489UL); 00217 00218 for (kk= 0; kk < MERSENNE_N - MERSENNE_M; kk++) 00219 { 00220 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); 00221 mt[kk] = mt[kk+MERSENNE_M] ^(y >> 1) ^ mag01[y & 0x1UL]; 00222 } 00223 00224 for (; kk< MERSENNE_N-1; kk++) 00225 { 00226 y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); 00227 mt[kk] = mt[kk+(MERSENNE_M - MERSENNE_N)] ^(y >> 1) ^ mag01[y & 0x1UL]; 00228 } 00229 00230 y = (mt[MERSENNE_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); 00231 mt[MERSENNE_N-1] = mt[MERSENNE_M-1] ^(y >> 1) ^ mag01[y & 0x1UL]; 00232 00233 mti = 0; 00234 } 00235 00236 y = mt[mti++]; 00237 00238 // Tempering 00239 y ^= (y >> 11); 00240 y ^= (y << 7) & 0x9d2c5680UL; 00241 y ^= (y << 15) & 0xefc60000UL; 00242 y ^= (y >> 18); 00243 00244 return y; 00245 } 00246 00247 #else 00248 00249 double Random::Next() 00250 { 00251 // Compute seed = (IA * seed) % IM without overflows 00252 // by Schrage's method 00253 long k = seed / IQ; 00254 seed = IA * (seed - k * IQ) - IR * k; 00255 if (seed < 0) seed += IM; 00256 00257 // Map to 0..NTAB-1 00258 int j = last/NDIV; 00259 00260 // Output value is shuffler[j], which is in turn replaced by seed 00261 last = shuffler[j]; 00262 shuffler[j] = seed; 00263 00264 // Map to 0.0 .. 1.0 excluding endpoints 00265 double temp = AM * last; 00266 if (temp > RNMX) return RNMX; 00267 return temp; 00268 } 00269 00270 unsigned long Random::NextInt() 00271 { 00272 // Compute seed = (IA * seed) % IM without overflows 00273 // by Schrage's method 00274 long k = seed / IQ; 00275 seed = IA * (seed - k * IQ) - IR * k; 00276 if (seed < 0) seed += IM; 00277 00278 // Map to 0..NTAB-1 00279 int j = last/NDIV; 00280 00281 // Output value is shuffler[j], which is in turn replaced by seed 00282 last = shuffler[j]; 00283 shuffler[j] = seed; 00284 00285 return last; 00286 } 00287 00288 #endif 00289 00290 double Random::Normal() 00291 { 00292 double v1, v2, fac, rsq; 00293 00294 if (!normSaved) // Do we need new numbers? 00295 { 00296 do 00297 { 00298 v1 = 2.0 * Next() - 1.0; // Pick two coordinates from 00299 v2 = 2.0 * Next() - 1.0; // -1 to +1 and check if they 00300 rsq = v1*v1 + v2*v2; // are in unit circle... 00301 } 00302 while (rsq >= 1.0 || rsq == 0.0); 00303 00304 fac = sqrt(-2.0 * log(rsq)/rsq); // Apply the Box-Muller 00305 normStore = v1 * fac; // transformation and save 00306 normSaved = 1; // one deviate for next time 00307 return v2 * fac; 00308 } 00309 else 00310 { 00311 normSaved = 0; 00312 return normStore; 00313 } 00314 } 00315 00316 void Random::Choose(int * array, int n, int k) 00317 { 00318 int choices = 1, others = 0; 00319 00320 if (k > n / 2) 00321 { 00322 choices = 0; 00323 others = 1; 00324 k = n - k; 00325 } 00326 00327 for (int i = 0; i < n; i++) 00328 array[i] = others; 00329 00330 while (k > 0) 00331 { 00332 int i = NextInt() % n; 00333 00334 if (array[i] == choices) continue; 00335 00336 array[i] = choices; 00337 k--; 00338 } 00339 } 00340 00341 void Random::Choose(int * array, float * weights, int n, int k) 00342 { 00343 int choices = 1, others = 0; 00344 00345 if (k > n / 2) 00346 { 00347 choices = 0; 00348 others = 1; 00349 k = n - k; 00350 } 00351 00352 // First calculate cumulative sums of weights ... 00353 float * cumulative = new float [n + 1]; 00354 00355 cumulative[0] = 0; 00356 for (int i = 1; i <= n; i++) 00357 cumulative[i] = cumulative[i - 1] + weights[i - 1]; 00358 00359 float & sum = cumulative[n], reject = 0.0; 00360 00361 for (int i = 0; i < n; i++) 00362 array[i] = others; 00363 00364 while (k > 0) 00365 { 00366 float weight = Next() * sum; 00367 00368 int hi = n, lo = 0, i = 0; 00369 00370 while (hi >= lo) 00371 { 00372 i = (hi + lo) / 2; 00373 00374 if (cumulative[i + 1] <= weight) 00375 lo = i + 1; 00376 else if (cumulative[i] >= weight) 00377 hi = i - 1; 00378 else break; 00379 } 00380 00381 if (array[i] == choices) continue; 00382 00383 array[i] = choices; 00384 reject += weights[i]; 00385 00386 // After selecting a substantial number of elements, update the cumulative 00387 // distribution -- to ensure that at least half of our samples produce a hit 00388 if (reject > sum * 0.50) 00389 { 00390 cumulative[0] = 0; 00391 for (int i = 1; i <= n; i++) 00392 if (array[i] != choices) 00393 cumulative[i] = cumulative[i - 1] + weights[i - 1]; 00394 else 00395 cumulative[i] = cumulative[i - 1]; 00396 00397 reject = 0.0; 00398 sum = cumulative[n]; 00399 } 00400 00401 k--; 00402 } 00403 00404 delete [] cumulative; 00405 } 00406 00407 Random globalRandom; 00408 00409