|
1 /* $Id$ */ |
|
2 |
|
3 #include "stdafx.h" |
|
4 #include "openttd.h" |
|
5 |
|
6 #ifdef MERSENNE_TWISTER |
|
7 |
|
8 // Source code for Mersenne Twister. |
|
9 // A Random number generator with much higher quality random numbers. |
|
10 |
|
11 #define N (624) // length of _mt_state vector |
|
12 #define M (397) // a period parameter |
|
13 #define K (0x9908B0DFU) // a magic constant |
|
14 #define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u |
|
15 #define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u |
|
16 #define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u |
|
17 #define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v |
|
18 |
|
19 static uint32 _mt_state[N+1]; // _mt_state vector + 1 extra to not violate ANSI C |
|
20 static uint32 *_mt_next; // _mt_next random value is computed from here |
|
21 static int _mt_left = -1; // can *_mt_next++ this many times before reloading |
|
22 |
|
23 void SeedMT(uint32 seed) |
|
24 { |
|
25 register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = _mt_state; |
|
26 register int j; |
|
27 |
|
28 for (_mt_left=0, *s++=x, j=N; --j; |
|
29 *s++ = (x*=69069U) & 0xFFFFFFFFU); |
|
30 } |
|
31 |
|
32 |
|
33 static uint32 ReloadMT(void) |
|
34 { |
|
35 register uint32 *p0=_mt_state, *p2=_mt_state+2, *pM=_mt_state+M, s0, s1; |
|
36 register int j; |
|
37 |
|
38 if (_mt_left < -1) |
|
39 SeedMT(4357U); |
|
40 |
|
41 _mt_left=N-1, _mt_next=_mt_state+1; |
|
42 |
|
43 for (s0=_mt_state[0], s1=_mt_state[1], j=N-M+1; --j; s0=s1, s1=*p2++) |
|
44 *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); |
|
45 |
|
46 for (pM=_mt_state, j=M; --j; s0=s1, s1=*p2++) |
|
47 *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); |
|
48 |
|
49 s1=_mt_state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); |
|
50 s1 ^= (s1 >> 11); |
|
51 s1 ^= (s1 << 7) & 0x9D2C5680U; |
|
52 s1 ^= (s1 << 15) & 0xEFC60000U; |
|
53 return(s1 ^ (s1 >> 18)); |
|
54 } |
|
55 |
|
56 |
|
57 uint32 RandomMT(void) |
|
58 { |
|
59 uint32 y; |
|
60 |
|
61 if (--_mt_left < 0) |
|
62 return ReloadMT(); |
|
63 |
|
64 y = *_mt_next++; |
|
65 y ^= (y >> 11); |
|
66 y ^= (y << 7) & 0x9D2C5680U; |
|
67 y ^= (y << 15) & 0xEFC60000U; |
|
68 return y ^ (y >> 18); |
|
69 } |
|
70 #else |
|
71 |
|
72 void SeedMT(uint32 seed) {} |
|
73 |
|
74 #endif /* MERSENNE_TWISTER */ |