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