| 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 |
} |
|---|