rev |
line source |
nuclear@0
|
1 #include <stdlib.h>
|
nuclear@0
|
2 #include <string.h>
|
nuclear@0
|
3 #include "rng.h"
|
nuclear@0
|
4
|
nuclear@0
|
5 //#define USE_STD_RAND
|
nuclear@0
|
6
|
nuclear@0
|
7 // defined at the end
|
nuclear@0
|
8 /**
|
nuclear@0
|
9 * tinymt32 internal state vector and parameters
|
nuclear@0
|
10 */
|
nuclear@0
|
11 struct tinymt32_t {
|
nuclear@0
|
12 uint32_t status[4];
|
nuclear@0
|
13 uint32_t mat1;
|
nuclear@0
|
14 uint32_t mat2;
|
nuclear@0
|
15 uint32_t tmat;
|
nuclear@0
|
16 };
|
nuclear@0
|
17
|
nuclear@0
|
18 #ifndef USE_STD_RAND
|
nuclear@0
|
19 static void tinymt32_init(tinymt32_t * random, uint32_t seed);
|
nuclear@0
|
20 inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random);
|
nuclear@0
|
21 inline static float tinymt32_generate_float(tinymt32_t * random);
|
nuclear@0
|
22 #endif
|
nuclear@0
|
23
|
nuclear@0
|
24 static RandGen defrng;
|
nuclear@0
|
25
|
nuclear@0
|
26 struct RandGenState {
|
nuclear@0
|
27 tinymt32_t st;
|
nuclear@0
|
28 };
|
nuclear@0
|
29
|
nuclear@0
|
30 RandGen::RandGen()
|
nuclear@0
|
31 {
|
nuclear@0
|
32 state = new RandGenState;
|
nuclear@0
|
33 memset(state, 0, sizeof *state);
|
nuclear@0
|
34 #ifndef USE_STD_RAND
|
nuclear@0
|
35 tinymt32_init(&state->st, 0);
|
nuclear@0
|
36 #endif
|
nuclear@0
|
37 }
|
nuclear@0
|
38
|
nuclear@0
|
39 RandGen::~RandGen()
|
nuclear@0
|
40 {
|
nuclear@0
|
41 delete state;
|
nuclear@0
|
42 }
|
nuclear@0
|
43
|
nuclear@0
|
44 void RandGen::seed(uint32_t s)
|
nuclear@0
|
45 {
|
nuclear@0
|
46 #ifndef USE_STD_RAND
|
nuclear@0
|
47 tinymt32_init(&state->st, s);
|
nuclear@0
|
48 #else
|
nuclear@0
|
49 srand(s);
|
nuclear@0
|
50 #endif
|
nuclear@0
|
51 }
|
nuclear@0
|
52
|
nuclear@0
|
53 uint32_t RandGen::generate()
|
nuclear@0
|
54 {
|
nuclear@0
|
55 #ifndef USE_STD_RAND
|
nuclear@0
|
56 return tinymt32_generate_uint32(&state->st);
|
nuclear@0
|
57 #else
|
nuclear@0
|
58 return rand();
|
nuclear@0
|
59 #endif
|
nuclear@0
|
60 }
|
nuclear@0
|
61
|
nuclear@0
|
62 float RandGen::generate_float()
|
nuclear@0
|
63 {
|
nuclear@0
|
64 #ifndef USE_STD_RAND
|
nuclear@0
|
65 return tinymt32_generate_float(&state->st);
|
nuclear@0
|
66 #else
|
nuclear@0
|
67 return (float)rand() / (float)RAND_MAX;
|
nuclear@0
|
68 #endif
|
nuclear@0
|
69 }
|
nuclear@0
|
70
|
nuclear@0
|
71 void rng_srand(uint32_t s)
|
nuclear@0
|
72 {
|
nuclear@0
|
73 defrng.seed(s);
|
nuclear@0
|
74 }
|
nuclear@0
|
75
|
nuclear@0
|
76 uint32_t rng_rand()
|
nuclear@0
|
77 {
|
nuclear@0
|
78 return defrng.generate();
|
nuclear@0
|
79 }
|
nuclear@0
|
80
|
nuclear@0
|
81 float rng_frand()
|
nuclear@0
|
82 {
|
nuclear@0
|
83 return defrng.generate_float();
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86
|
nuclear@0
|
87 #ifndef USE_STD_RAND
|
nuclear@0
|
88 /**
|
nuclear@0
|
89 * @file tinymt32.h
|
nuclear@0
|
90 *
|
nuclear@0
|
91 * @brief Tiny Mersenne Twister only 127 bit internal state
|
nuclear@0
|
92 *
|
nuclear@0
|
93 * @author Mutsuo Saito (Hiroshima University)
|
nuclear@0
|
94 * @author Makoto Matsumoto (University of Tokyo)
|
nuclear@0
|
95 *
|
nuclear@0
|
96 * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
|
nuclear@0
|
97 * Hiroshima University and The University of Tokyo.
|
nuclear@0
|
98 * All rights reserved.
|
nuclear@0
|
99 *
|
nuclear@0
|
100 * The 3-clause BSD License is applied to this software, see
|
nuclear@0
|
101 * LICENSE.txt
|
nuclear@0
|
102 */
|
nuclear@0
|
103 #define TINYMT32_MEXP 127
|
nuclear@0
|
104 #define TINYMT32_SH0 1
|
nuclear@0
|
105 #define TINYMT32_SH1 10
|
nuclear@0
|
106 #define TINYMT32_SH8 8
|
nuclear@0
|
107 #define TINYMT32_MASK UINT32_C(0x7fffffff)
|
nuclear@0
|
108 #define TINYMT32_MUL (1.0f / 4294967296.0f)
|
nuclear@0
|
109
|
nuclear@0
|
110 /**
|
nuclear@0
|
111 * This function changes internal state of tinymt32.
|
nuclear@0
|
112 * Users should not call this function directly.
|
nuclear@0
|
113 * @param random tinymt internal status
|
nuclear@0
|
114 */
|
nuclear@0
|
115 inline static void tinymt32_next_state(tinymt32_t * random) {
|
nuclear@0
|
116 uint32_t x;
|
nuclear@0
|
117 uint32_t y;
|
nuclear@0
|
118
|
nuclear@0
|
119 y = random->status[3];
|
nuclear@0
|
120 x = (random->status[0] & TINYMT32_MASK)
|
nuclear@0
|
121 ^ random->status[1]
|
nuclear@0
|
122 ^ random->status[2];
|
nuclear@0
|
123 x ^= (x << TINYMT32_SH0);
|
nuclear@0
|
124 y ^= (y >> TINYMT32_SH0) ^ x;
|
nuclear@0
|
125 random->status[0] = random->status[1];
|
nuclear@0
|
126 random->status[1] = random->status[2];
|
nuclear@0
|
127 random->status[2] = x ^ (y << TINYMT32_SH1);
|
nuclear@0
|
128 random->status[3] = y;
|
nuclear@0
|
129 random->status[1] ^= -((int32_t)(y & 1)) & random->mat1;
|
nuclear@0
|
130 random->status[2] ^= -((int32_t)(y & 1)) & random->mat2;
|
nuclear@0
|
131 }
|
nuclear@0
|
132
|
nuclear@0
|
133 /**
|
nuclear@0
|
134 * This function outputs 32-bit unsigned integer from internal state.
|
nuclear@0
|
135 * Users should not call this function directly.
|
nuclear@0
|
136 * @param random tinymt internal status
|
nuclear@0
|
137 * @return 32-bit unsigned pseudorandom number
|
nuclear@0
|
138 */
|
nuclear@0
|
139 inline static uint32_t tinymt32_temper(tinymt32_t * random) {
|
nuclear@0
|
140 uint32_t t0, t1;
|
nuclear@0
|
141 t0 = random->status[3];
|
nuclear@0
|
142 #if defined(LINEARITY_CHECK)
|
nuclear@0
|
143 t1 = random->status[0]
|
nuclear@0
|
144 ^ (random->status[2] >> TINYMT32_SH8);
|
nuclear@0
|
145 #else
|
nuclear@0
|
146 t1 = random->status[0]
|
nuclear@0
|
147 + (random->status[2] >> TINYMT32_SH8);
|
nuclear@0
|
148 #endif
|
nuclear@0
|
149 t0 ^= t1;
|
nuclear@0
|
150 t0 ^= -((int32_t)(t1 & 1)) & random->tmat;
|
nuclear@0
|
151 return t0;
|
nuclear@0
|
152 }
|
nuclear@0
|
153
|
nuclear@0
|
154 /**
|
nuclear@0
|
155 * This function outputs 32-bit unsigned integer from internal state.
|
nuclear@0
|
156 * @param random tinymt internal status
|
nuclear@0
|
157 * @return 32-bit unsigned integer r (0 <= r < 2^32)
|
nuclear@0
|
158 */
|
nuclear@0
|
159 inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) {
|
nuclear@0
|
160 tinymt32_next_state(random);
|
nuclear@0
|
161 return tinymt32_temper(random);
|
nuclear@0
|
162 }
|
nuclear@0
|
163
|
nuclear@0
|
164 /**
|
nuclear@0
|
165 * This function outputs floating point number from internal state.
|
nuclear@0
|
166 * This function is implemented using multiplying by 1 / 2^32.
|
nuclear@0
|
167 * floating point multiplication is faster than using union trick in
|
nuclear@0
|
168 * my Intel CPU.
|
nuclear@0
|
169 * @param random tinymt internal status
|
nuclear@0
|
170 * @return floating point number r (0.0 <= r < 1.0)
|
nuclear@0
|
171 */
|
nuclear@0
|
172 inline static float tinymt32_generate_float(tinymt32_t * random) {
|
nuclear@0
|
173 tinymt32_next_state(random);
|
nuclear@0
|
174 return tinymt32_temper(random) * TINYMT32_MUL;
|
nuclear@0
|
175 }
|
nuclear@0
|
176
|
nuclear@0
|
177 #define MIN_LOOP 8
|
nuclear@0
|
178 #define PRE_LOOP 8
|
nuclear@0
|
179
|
nuclear@0
|
180 /**
|
nuclear@0
|
181 * This function certificate the period of 2^127-1.
|
nuclear@0
|
182 * @param random tinymt state vector.
|
nuclear@0
|
183 */
|
nuclear@0
|
184 static void period_certification(tinymt32_t * random) {
|
nuclear@0
|
185 if ((random->status[0] & TINYMT32_MASK) == 0 &&
|
nuclear@0
|
186 random->status[1] == 0 &&
|
nuclear@0
|
187 random->status[2] == 0 &&
|
nuclear@0
|
188 random->status[3] == 0) {
|
nuclear@0
|
189 random->status[0] = 'T';
|
nuclear@0
|
190 random->status[1] = 'I';
|
nuclear@0
|
191 random->status[2] = 'N';
|
nuclear@0
|
192 random->status[3] = 'Y';
|
nuclear@0
|
193 }
|
nuclear@0
|
194 }
|
nuclear@0
|
195
|
nuclear@0
|
196 /**
|
nuclear@0
|
197 * This function initializes the internal state array with a 32-bit
|
nuclear@0
|
198 * unsigned integer seed.
|
nuclear@0
|
199 * @param random tinymt state vector.
|
nuclear@0
|
200 * @param seed a 32-bit unsigned integer used as a seed.
|
nuclear@0
|
201 */
|
nuclear@0
|
202 static void tinymt32_init(tinymt32_t * random, uint32_t seed) {
|
nuclear@0
|
203 random->status[0] = seed;
|
nuclear@0
|
204 random->status[1] = random->mat1;
|
nuclear@0
|
205 random->status[2] = random->mat2;
|
nuclear@0
|
206 random->status[3] = random->tmat;
|
nuclear@0
|
207 for (int i = 1; i < MIN_LOOP; i++) {
|
nuclear@0
|
208 random->status[i & 3] ^= i + UINT32_C(1812433253)
|
nuclear@0
|
209 * (random->status[(i - 1) & 3]
|
nuclear@0
|
210 ^ (random->status[(i - 1) & 3] >> 30));
|
nuclear@0
|
211 }
|
nuclear@0
|
212 period_certification(random);
|
nuclear@0
|
213 for (int i = 0; i < PRE_LOOP; i++) {
|
nuclear@0
|
214 tinymt32_next_state(random);
|
nuclear@0
|
215 }
|
nuclear@0
|
216 }
|
nuclear@0
|
217 #endif // !defined(USE_STD_RAND)
|