libStatGen Software  1
Random.cpp
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends