Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/numerics/rng/mt19937.cc

Go to the documentation of this file.
00001 /*
00002  * lib/numerics/rng/mt19937.cc
00003  * 
00004  * Implementation of fast Mersenne Twister PRNG with period 2^19937-1. 
00005  * 
00006  * Converted to class 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ based on 
00007  * mt19937ar-cok.c by Takuji Nishimura and Makoto Matsumoto; see below. 
00008  * 
00009  * This file may be distributed and/or modified under the terms of the 
00010  * GNU General Public License version 2 as published by the Free Software 
00011  * Foundation. (See COPYING.GPL for details.)
00012  * 
00013  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00014  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00015  * 
00016  * Original copyright and legal info of mt19937ar-cok.c (the C version). 
00017 --------------------------------------------------------------------------------
00018    A C-program for MT19937, with initialization improved 2002/2/10.
00019    Coded by Takuji Nishimura and Makoto Matsumoto.
00020    This is a faster version by taking Shawn Cokus's optimization,
00021    Matthe Bellew's simplification, Isaku Wada's real version.
00022 
00023    Before using, initialize the state by using init_genrand(seed) 
00024    or init_by_array(init_key, key_length).
00025 
00026    Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
00027    All rights reserved.                          
00028 
00029    Redistribution and use in source and binary forms, with or without
00030    modification, are permitted provided that the following conditions
00031    are met:
00032 
00033      1. Redistributions of source code must retain the above copyright
00034         notice, this list of conditions and the following disclaimer.
00035 
00036      2. Redistributions in binary form must reproduce the above copyright
00037         notice, this list of conditions and the following disclaimer in the
00038         documentation and/or other materials provided with the distribution.
00039 
00040      3. The names of its contributors may not be used to endorse or promote 
00041         products derived from this software without specific prior written 
00042         permission.
00043 
00044    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00045    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00046    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00047    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00048    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00049    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00050    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00051    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00052    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00053    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00054    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00055 
00056 
00057    Any feedback is very welcome.
00058    http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
00059    email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
00060 */
00061 
00062 #include "mt19937.h"
00063 
00064 namespace NUM   // numerics
00065 {
00066 
00067 void RandomNumberGenerator_MersenneTwister19937::seed(uint32 s)
00068 {
00069     state[0] = s & 0xffffffffU;
00070     
00071     for(int j=1; j<N; j++)
00072     {
00073         /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
00074         /* In the previous versions, MSBs of the seed affect   */
00075         /* only MSBs of the array state[].                     */
00076         /* 2002/01/09 modified by Makoto Matsumoto             */
00077         state[j] = (1812433253U * (state[j-1] ^ (state[j-1] >> 30)) + j); 
00078         // The following should not be needed since we're using uint32 (WW). 
00079         // (But never mind since it gets optimized away (verified gcc-3.4.2).)
00080         state[j] &= 0xffffffffU;  /* for >32 bit machines */
00081     }
00082     
00083     left=1;
00084 }
00085 
00086 
00087 void RandomNumberGenerator_MersenneTwister19937::seed(const uint32 *init_key,
00088     int key_length)
00089 {
00090     seed(19650218U);
00091     
00092     int i=1;
00093     int j=0;
00094     int k = (N>key_length ? N : key_length);
00095     for(; k; k--)
00096     {
00097         state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525U))
00098                    + init_key[j] + j;   /* non linear */
00099         // The following should not be needed since we're using uint32 (WW). 
00100         // (But never mind since it gets optimized away (verified gcc-3.4.2).)
00101         state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
00102         
00103         if(++i>=N)
00104         {  state[0] = state[N-1];  i=1;  }
00105         if(++j>=key_length)  j=0;
00106     }
00107     
00108     for(k=N-1; k; k--)
00109     {
00110         state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) 
00111                     * 1566083941U)) - i; /* non linear */
00112         // The following should not be needed since we're using uint32 (WW). 
00113         // (But never mind since it gets optimized away (verified gcc-3.4.2).)
00114         state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
00115         
00116         if(++i>=N)  { state[0] = state[N-1];  i=1;  }
00117     }
00118     
00119     state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ 
00120     left=1;
00121 }
00122 
00123 
00124 void RandomNumberGenerator_MersenneTwister19937::next_state()
00125 {
00126     left = N;
00127     next = state;
00128     
00129     uint32 *p=state;
00130     for(int j=N-M+1; --j; p++) 
00131         *p = p[M] ^ TWIST(p[0], p[1]);
00132     
00133     for(int j=M; --j; p++) 
00134         *p = p[M-N] ^ TWIST(p[0], p[1]);
00135     
00136     *p = p[M-N] ^ TWIST(p[0], state[0]);
00137 }
00138 
00139 }  // end of namespace NUM
00140 
00141 
00142 #if 0
00143 #include <stdio.h>  /* test program */
00144 
00145 /*
00146  * This test program should produce the following: 
00147  * ===============================================
00148  * 
00149  * (Verified 11/2004 by Wolfgang Wieser when converting the C code into 
00150  * the class RandomNumberGenerator_MersenneTwister19937.) 
00151  * 
00152  
00153 1000 outputs of genrand_int32()
00154 1067595299  955945823  477289528 4107218783 4228976476 
00155 3344332714 3355579695  227628506  810200273 2591290167 
00156 2560260675 3242736208  646746669 1479517882 4245472273 
00157 1143372638 3863670494 3221021970 1773610557 1138697238 
00158 1421897700 1269916527 2859934041 1764463362 3874892047 
00159 3965319921   72549643 2383988930 2600218693 3237492380 
00160 2792901476  725331109  605841842  271258942  715137098 
00161 3297999536 1322965544 4229579109 1395091102 3735697720 
00162 2101727825 3730287744 2950434330 1661921839 2895579582 
00163 2370511479 1004092106 2247096681 2111242379 3237345263 
00164 4082424759  219785033 2454039889 3709582971  835606218 
00165 2411949883 2735205030  756421180 2175209704 1873865952 
00166 2762534237 4161807854 3351099340  181129879 3269891896 
00167  776029799 2218161979 3001745796 1866825872 2133627728 
00168   34862734 1191934573 3102311354 2916517763 1012402762 
00169 2184831317 4257399449 2899497138 3818095062 3030756734 
00170 [...]
00171 
00172 1000 outputs of genrand_real2()
00173 0.76275443 0.99000644 0.98670464 0.10143112 0.27933125 
00174 0.69867227 0.94218740 0.03427201 0.78842173 0.28180608 
00175 0.92179002 0.20785655 0.54534773 0.69644020 0.38107718 
00176 0.23978165 0.65286910 0.07514568 0.22765211 0.94872929 
00177 0.74557914 0.62664415 0.54708246 0.90959343 0.42043116 
00178 0.86334511 0.19189126 0.14718544 0.70259889 0.63426346 
00179 0.77408121 0.04531601 0.04605807 0.88595519 0.69398270 
00180 0.05377184 0.61711170 0.05565708 0.10133577 0.41500776 
00181 0.91810699 0.22320679 0.23353705 0.92871862 0.98897234 
00182 0.19786706 0.80558809 0.06961067 0.55840445 0.90479405 
00183 0.63288060 0.95009721 0.54948447 0.20645042 0.45000959 
00184 0.87050869 0.70806991 0.19406895 0.79286390 0.49332866 
00185 0.78483914 0.75145146 0.12341941 0.42030252 0.16728160 
00186 0.59906494 0.37575460 0.97815160 0.39815952 0.43595080 
00187 0.04952478 0.33917805 0.76509902 0.61034321 0.90654701 
00188 0.92915732 0.85365931 0.18812377 0.65913428 0.28814566 
00189 [...]
00190 */ 
00191 
00192 int main()
00193 {
00194     CritAssert(sizeof(uint32)==4);  // test app
00195     uint32 _x=0xffffffff;
00196     CritAssert(_x>=0);   // test app
00197     
00198     uint32 init[4]={0x123, 0x234, 0x345, 0x456}, length=4;
00199     /* This is an example of initializing by an array. */
00200     /* You may use seed(seed) with any 32bit integer   */
00201     /* as a seed for a simpler initialization          */
00202     NUM::RandomNumberGenerator_MersenneTwister19937 rng(init, length);
00203     
00204     printf("1000 outputs of genrand_int32()\n");
00205     for(int i=0; i<1000; i++)
00206     {
00207         printf("%10u ", rng.rand_uint32());
00208         if(i%5==4) printf("\n");
00209     }
00210     
00211     printf("\n1000 outputs of genrand_real2()\n");
00212     for(int i=0; i<1000; i++)
00213     {
00214         printf("%10.8f ", rng.rand_dbl32o());
00215         if(i%5==4) printf("\n");
00216     }
00217     
00218     return(0);
00219 }
00220 #endif

Generated on Sat Feb 19 22:33:46 2005 for Ray by doxygen 1.3.5