-
Notifications
You must be signed in to change notification settings - Fork 6
/
mtrand.cpp
156 lines (119 loc) · 3.44 KB
/
mtrand.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "mtrand.hpp"
#include <iostream>
// Global parameters
#define SEED_SIZE 4
// Mersenne Twister parameters -- stripped from the PHP source
#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */
#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */
#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */
#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
static inline uint32_t
php_twist(uint32_t m, uint32_t u, uint32_t v)
{
return (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(uint32_t)(loBit(u))) & 0x9908b0dfU));
}
static inline uint32_t
mt_twist(uint32_t m, uint32_t u, uint32_t v)
{
return (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(uint32_t)(loBit(v))) & 0x9908b0dfU));
}
#define RAND_RANGE(__n, __min, __max, __tmax) \
(__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
#define PHP_MT_RAND_MAX ((long) (0x7FFFFFFF)) /* (1<<31) - 1 */
// Some structures and Macros to make our life easier...
void
MTRand::mtInitialize(uint32_t seed)
{
/* Initialize generator state with seed
See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
In previous versions, most significant bits (MSBs) of the seed affect
only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */
register uint32_t *s = mtInfo.state;
register uint32_t *r = mtInfo.state;
register int i = 1;
*s++ = seed & 0xffffffffU;
for( ; i < N; ++i ) {
*s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU;
r++;
}
}
void
MTRand::mtReload()
{
/* Generate N new values in state
Made clearer and faster by Matthew Bellew ([email protected]) */
register uint32_t *p = mtInfo.state;
register int i;
register uint32_t (*twist)(uint32_t, uint32_t, uint32_t) =
(PHPMtRand)? php_twist : mt_twist;
for (i = N - M; i--; ++p)
*p = twist(p[M], p[0], p[1]);
for (i = M; --i; ++p)
*p = twist(p[M-N], p[0], p[1]);
*p = twist(p[M-N], p[0], mtInfo.state[0]);
mtInfo.left = N;
mtInfo.next = mtInfo.state;
}
void
MTRand::mt_srand(uint32_t seed) {
mtInitialize(seed);
mtInfo.left = 0;
return;
}
uint32_t
MTRand::mt_rand()
{
/* Pull a 32-bit integer from the generator state
Every other access function simply transforms the numbers extracted here */
register uint32_t s1;
if (mtInfo.left == 0)
mtReload();
-- (mtInfo.left);
s1 = *mtInfo.next ++;
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9d2c5680U;
s1 ^= (s1 << 15) & 0xefc60000U;
s1 ^= (s1 >> 18) ;
return s1;
}
uint32_t
MTRand::php_mt_rand()
{
return mt_rand() >> 1;
}
void
MTRand::setState(uint32_t *s)
{
memcpy(mtInfo.state, s, N*sizeof(uint32_t));
mtInfo.left = 0;
mtInfo.next = mtInfo.state;
}
#if 0
int main(int argc, char *argv[])
{
MTRand gen(PHP_MT_RAND);
uint32_t s[N];
gen.mt_srand(atoi(argv[1]));
for (int i = 0; i < 15; i ++){
unsigned long num = gen.php_mt_rand();
//RAND_RANGE(num, 0, 36, 0x7fffffff);
std::cout << num << std::endl;
}
return 0;
for (int i = 0; i < 1000000; i ++){
gen.mt_srand(i);
gen.mt_rand();
}
return 0;
memcpy(s, gen.getState(), N*sizeof(uint32_t));
std::cout << gen.mt_rand() << std::endl;
std::cout << gen.mt_rand() << std::endl;
for (int i = 0; i < 100; i ++) {
gen.mt_rand();
}
gen.setState(s);
std::cout << gen.mt_rand() << std::endl;
std::cout << gen.mt_rand() << std::endl;
return 0;
}
#endif