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