root/trunk/mt.d

Revision 37, 8.4 kB (checked in by qbert, 5 years ago)

--

Line 
1 module mt;
2
3 version ( Tango )
4 {
5   import tango.text.locale.Win32;
6   alias getUtcGime getUTC ;
7 }
8 else version ( Phobos )
9 {
10   import std.date;
11   alias  getUTCtime getUTC;
12 }
13
14 /*
15    A D-program ported by Derek Parnell 2006/04/12,
16    based on the C-program for MT19937,  with initialization improved 2002/1/26,
17       coded by Takuji Nishimura and Makoto Matsumoto.
18
19    Before using, initialize the state by using init_genrand(seed)
20    or init_by_array(init_key). However, if you do not
21    a seed is generated based on the current date-time of the system.
22
23    Derek Parnell: init_genrand, init_bt_array, and genrand_int32 all
24    now take an optional boolean parameter. If 'true' then an new seed
25    is generated using some limited entropy (clock and previous random).
26    This is to increase the non-sequential set of returned values.
27
28    Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
29    All rights reserved.
30
31    Redistribution and use in source and binary forms, with or without
32    modification, are permitted provided that the following conditions
33    are met:
34
35      1. Redistributions of source code must retain the above copyright
36         notice, this list of conditions and the following disclaimer.
37
38      2. Redistributions in binary form must reproduce the above copyright
39         notice, this list of conditions and the following disclaimer in the
40         documentation and/or other materials provided with the distribution.
41
42      3. The names of its contributors may not be used to endorse or promote
43         products derived from this software without specific prior written
44         permission.
45
46    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
49    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
50    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
51    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
52    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
53    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
54    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
55    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
56    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
58
59    Any feedback is very welcome.
60    http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
61    email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
62 */
63
64 private
65 {
66
67
68     /* Period parameters */
69     const uint N          = 624;
70     const uint M          = 397;
71     const uint MATRIX_A   = 0x9908b0df;   /* constant vector a */
72     const uint UPPER_MASK = 0x80000000; /* most significant w-r bits */
73     const uint LOWER_MASK = 0x7fffffff; /* least significant r bits */
74
75     uint[N] mt; /* the array for the state vector  */
76     uint mti=mt.length+1; /* mti==mt.length+1 means mt[] is not initialized */
77     uint vLastRand; /* The most recent random uint returned. */
78 }
79
80 /* initializes mt[] with a seed */
81 void init_genrand(uint s, bool pAddEntropy = false)
82 {
83     mt[0]= (s + (pAddEntropy ? vLastRand + getUTC() + cast(uint)&init_genrand
84                       : 0))
85             &  0xffffffffUL;
86     for (mti=1; mti<mt.length; mti++)
87     {
88         mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
89         /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
90         /* In the previous versions, MSBs of the seed affect   */
91         /* only MSBs of the array mt[].                        */
92         /* 2002/01/09 modified by Makoto Matsumoto             */
93         mt[mti] &= 0xffffffffUL;
94         /* for >32 bit machines */
95     }
96 }
97
98 /* initialize by an array with array-length */
99 /* init_key is the array for initializing keys */
100 /* slight change for C++, 2004/2/26 */
101 void init_by_array(uint[] init_key, bool pAddEntropy = false)
102 {
103     int i, j, k;
104     init_genrand( 19650218UL, pAddEntropy);
105     i=1;
106     j=0;
107
108     for (k = (mt.length > init_key.length ? mt.length : init_key.length); k; k--)
109     {
110         mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
111           + init_key[j] + j; /* non linear */
112         mt[i] &=  0xffffffffUL; /* for WORDSIZE > 32 machines */
113         i++;
114         j++;
115
116         if (i >= mt.length)
117         {
118             mt[0] = mt[mt.length-1];
119             i=1;
120         }
121
122         if (j >= init_key.length)
123             j=0;
124     }
125
126     for (k=mt.length-1; k; k--)
127     {
128         mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
129           - i; /* non linear */
130         mt[i] &=  0xffffffffUL; /* for WORDSIZE > 32 machines */
131         i++;
132
133         if (i>=mt.length)
134         {
135             mt[0] = mt[mt.length-1];
136             i=1;
137         }
138     }
139     mt[0] |=  0x80000000UL; /* MSB is 1; assuring non-zero initial array */
140     mti=0;
141
142 }
143
144 /* generates a random number on [0,0xffffffff]-interval */
145 uint genrand_int32(bool pAddEntropy = false)
146 {
147     uint y;
148     static uint mag01[2] =[0, MATRIX_A];
149     /* mag01[x] = x * MATRIX_A  for x=0,1 */
150
151     if (mti >= mt.length) { /* fill the entire mt[] at one time */
152         int kk;
153
154         if (pAddEntropy || mti > mt.length)   /* if init_genrand() has not been called, */
155         {
156             init_genrand( 5489UL, pAddEntropy ); /* a default initial seed is used */
157         }
158
159         for (kk=0;kk<mt.length-M;kk++)
160         {
161             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
162             mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 1UL];
163         }
164         for (;kk<mt.length-1;kk++) {
165             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
166             mt[kk] = mt[kk+(M-mt.length)] ^ (y >> 1) ^ mag01[y & 1UL];
167         }
168         y = (mt[mt.length-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
169         mt[mt.length-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 1UL];
170
171         mti = 0;
172     }
173
174     y = mt[mti++];
175
176     /* Tempering */
177     y ^= (y >> 11);
178     y ^= (y << 7)  &  0x9d2c5680UL;
179     y ^= (y << 15) &  0xefc60000UL;
180     y ^= (y >> 18);
181
182     vLastRand = y;
183     return y;
184 }
185
186 /* generates a random number on [0,0x7fffffff]-interval */
187 long genrand_int31()
188 {
189     return cast(long)(genrand_int32()>>1);
190 }
191
192 /* generates a random number on [0,1]-real-interval */
193 double genrand_real1()
194 {
195     return genrand_int32()*(1.0/cast(double)uint.max);
196     /* divided by 2^32-1 */
197 }
198
199 /* generates a random number on [0,1)-real-interval */
200 double genrand_real2()
201 {
202     return genrand_int32()*(1.0/(cast(double)uint.max+1.0));
203     /* divided by 2^32 */
204 }
205
206 /* generates a random number on (0,1)-real-interval */
207 double genrand_real3()
208 {
209     return ((cast(double)genrand_int32()) + 0.5)*(1.0/(cast(double)uint.max+1.0));
210     /* divided by 2^32 */
211 }
212
213 /* generates a random number on [0,1) with 53-bit resolution*/
214 double genrand_res53()
215 {
216     uint a=genrand_int32()>>5, b=genrand_int32()>>6;
217     return(a*67108864.0+b)*(1.0/9007199254740992.0);
218 }
219 /* These real versions are due to Isaku Wada, 2002/01/09 added */
220
221 /* generates a random number in [low,high] interval - Derek Parnell */
222 template genrand_range(T)
223 {
224 T genrand_range(T pLow, T pHigh,bool pAddEntropy = false)
225 {
226     T lResult;
227     T lInterval;
228     T lTemp;
229     uint lRand;
230
231     if (pLow == pHigh)
232         return pLow;
233
234     if (pLow > pHigh)
235     {
236         lResult = pHigh;
237         pHigh = pLow;
238         pLow = lResult;
239     }
240     lRand = genrand_int32(pAddEntropy);
241
242     static if ( is(T == real) ||
243                 is(T == double)  ||
244                 is(T == float) )
245     {
246         lRand = genrand_int32(pAddEntropy);
247         lInterval = cast(real)pHigh - cast(real)pLow;
248         lTemp = cast(real)lRand / uint.max;
249         lResult =  lInterval * lTemp + pLow;
250     }
251     else static if ( is(T == ulong) ||
252                      is(T == long)  ||
253                      is(T == uint)  ||
254                      is(T == int)   ||
255                      is(T == ushort)||
256                      is(T == short) ||
257                      is(T == ubyte) ||
258                      is(T == byte) )
259     {
260         lInterval = pHigh - pLow + 1;
261         lResult = lRand % lInterval + pLow;
262     }
263     else
264     {
265         pragma(msg, "ERROR! genrand_range!() Can only use an integer or floating point type");
266         static assert(0);
267     }
268
269     return lResult;
270 }
271 }
272
273 struct MT_State
274 {
275     uint Index;
276     uint[N] Seeds;
277 }
278
279 MT_State* GetState()
280 {
281     MT_State* lTemp = new MT_State;
282     lTemp.Index = mti;
283     lTemp.Seeds[] = mt[];
284
285     return lTemp;
286 }
287
288 void SetState(MT_State* pSaved)
289 {
290     mti = pSaved.Index;
291     mt[] = pSaved.Seeds[];
292
293 }
Note: See TracBrowser for help on using the browser.