Scythe-1.0.3
mersenne.h
Go to the documentation of this file.
00001 /* 
00002  * Scythe Statistical Library
00003  * Copyright (C) 2000-2002 Andrew D. Martin and Kevin M. Quinn;
00004  * 2002-present Andrew D. Martin, Kevin M. Quinn, and Daniel
00005  * Pemstein.  All Rights Reserved.
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * under the terms of the GNU General Public License as published by
00009  * Free Software Foundation; either version 2 of the License, or (at
00010  * your option) any later version.  See the text files COPYING
00011  * and LICENSE, distributed with this source code, for further
00012  * information.
00013  * --------------------------------------------------------------------
00014  * scythestat/rng/mersenne.h
00015  *
00016  * Provides the class definition for the mersenne random number
00017  * generator.  This class extends the base rng class by providing an
00018  * implementation of runif() based on an implementation of the
00019  * mersenne twister, released under the following license:
00020  *
00021  * A C-program for MT19937, with initialization improved 2002/1/26.
00022  * Coded by Takuji Nishimura and Makoto Matsumoto.
00023  * 
00024  * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
00025  * All rights reserved.
00026  *
00027  * Redistribution and use in source and binary forms, with or without
00028  * modification, are permitted provided that the following conditions
00029  * are met:
00030  *
00031  * 1. Redistributions of source code must retain the above copyright
00032  *    notice, this list of conditions and the following disclaimer.
00033  *
00034  * 2. Redistributions in binary form must reproduce the above
00035  *    copyright
00036  *    notice, this list of conditions and the following disclaimer
00037  *    in the documentation and/or other materials provided with the
00038  *    distribution.
00039  *
00040  * 3. The names of its contributors may not be used to endorse or
00041  *    promote products derived from this software without specific
00042  *    prior written permission.
00043  *
00044  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
00045  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
00046  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00047  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00048  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00049  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL,
00050  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00051  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
00052  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00053  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00054  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00055  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00056  * POSSIBILITY OF SUCH DAMAGE.
00057  *
00058  * For more information see:
00059  * http://www.math.keio.ac.jp/matumoto/emt.html
00060  *
00061  */
00062 
00072 #ifndef SCYTHE_MERSENNE_H
00073 #define SCYTHE_MERSENNE_H
00074 
00075 #ifdef SCYTHE_COMPILE_DIRECT
00076 #include "rng.h"
00077 #else
00078 #include "scythestat/rng.h"
00079 #endif
00080 
00081 namespace scythe {
00082 
00083 #ifdef __MINGW32__
00084   /* constant vector a */
00085   static const unsigned long MATRIX_A = 0x9908b0dfUL;
00086   
00087   /* most significant w-r bits */
00088   static const unsigned long UPPER_MASK = 0x80000000UL;
00089   
00090   /* least significant r bits */
00091   static const unsigned long LOWER_MASK = 0x7fffffffUL;
00092 #else
00093   namespace {
00094     /* constant vector a */
00095     const unsigned long MATRIX_A = 0x9908b0dfUL;
00096     
00097     /* most significant w-r bits */
00098     const unsigned long UPPER_MASK = 0x80000000UL;
00099     
00100     /* least significant r bits */
00101     const unsigned long LOWER_MASK = 0x7fffffffUL;
00102   }
00103 #endif
00104 
00120   class mersenne: public rng<mersenne>
00121   {
00122     public:
00123 
00135       mersenne ()
00136         : rng<mersenne> (),
00137           mti (N + 1)
00138       {}
00139 
00149       mersenne (const mersenne &m)
00150         : rng<mersenne> (),
00151           mti (m.mti)
00152       {
00153       }
00154 
00167       void initialize (unsigned long s)
00168       {
00169         mt[0]= s & 0xffffffffUL;
00170         for (mti=1; mti<N; mti++) {
00171           mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30))
00172               + mti); 
00173           /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
00174           /* In the previous versions, MSBs of the seed affect   */
00175           /* only MSBs of the array mt[].                        */
00176           /* 2002/01/09 modified by Makoto Matsumoto             */
00177           mt[mti] &= 0xffffffffUL;
00178           /* for >32 bit machines */
00179         }
00180       }
00181       
00193       inline double runif()
00194       {
00195         return (((double) genrand_int32()) + 0.5) * 
00196           (1.0 / 4294967296.0);
00197       }
00198 
00199       /* We have to override the overloaded forms of runif because
00200        * overloading the no-arg runif() hides the base class
00201        * definition; C++ stops looking once it finds the above.
00202        */
00224       template <matrix_order O, matrix_style S>
00225       inline Matrix<double,O,S> runif(unsigned int rows, 
00226                                       unsigned int cols)
00227       {
00228         return rng<mersenne>::runif<O,S>(rows, cols);
00229       }
00230 
00252       Matrix<double,Col,Concrete> runif(unsigned int rows,
00253                                         unsigned int cols)
00254       {
00255         return rng<mersenne>::runif<Col,Concrete>(rows, cols);
00256       }
00257 
00258       /* generates a random number on [0,0xffffffff]-interval */
00267       unsigned long genrand_int32()
00268       {
00269         unsigned long y;
00270         static unsigned long mag01[2]={0x0UL, MATRIX_A};
00271         /* mag01[x] = x * MATRIX_A  for x=0,1 */
00272 
00273         if (mti >= N) { /* generate N words at one time */
00274           int kk;
00275 
00276           if (mti == N+1)   // if init_genrand() has not been called,
00277             this->initialize(5489UL); // a default initial seed is used
00278 
00279           for (kk=0;kk<N-M;kk++) {
00280             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00281             mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
00282           }
00283           for (;kk<N-1;kk++) {
00284             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00285             mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
00286           }
00287           y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
00288           mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
00289 
00290           mti = 0;
00291         }
00292       
00293         y = mt[mti++];
00294 
00295         /* Tempering */
00296         y ^= (y >> 11);
00297         y ^= (y << 7) & 0x9d2c5680UL;
00298         y ^= (y << 15) & 0xefc60000UL;
00299         y ^= (y >> 18);
00300 
00301         return y;
00302       }
00303     
00304     protected:
00305       /* Period parameters */
00306       static const int N = 624;
00307       static const int M = 398;
00308     
00309       /* the array for the state vector  */
00310       unsigned long mt[N];
00311 
00312       /* mti==N+1 means mt[N] is not initialized */
00313       int mti;
00314   };
00315 
00316 }
00317 
00318 #endif /* SCYTHE_MERSENNE_H */