Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | #ifndef TINYMT32_H | |||
2 | #define TINYMT32_H | |||
3 | /** | |||
4 | * @file tinymt32.h | |||
5 | * | |||
6 | * @brief Tiny Mersenne Twister only 127 bit internal state | |||
7 | * | |||
8 | * @author Mutsuo Saito (Hiroshima University) | |||
9 | * @author Makoto Matsumoto (University of Tokyo) | |||
10 | * | |||
11 | * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, | |||
12 | * Hiroshima University and The University of Tokyo. | |||
13 | * All rights reserved. | |||
14 | * | |||
15 | * The 3-clause BSD License is applied to this software, see | |||
16 | * LICENSE.txt | |||
17 | */ | |||
18 | ||||
19 | #include <stdint.h> | |||
20 | #include <inttypes.h> | |||
21 | ||||
22 | #define TINYMT32_MEXP 127 | |||
23 | #define TINYMT32_SH0 1 | |||
24 | #define TINYMT32_SH1 10 | |||
25 | #define TINYMT32_SH8 8 | |||
26 | #define TINYMT32_MASK UINT32_C(0x7fffffff) | |||
27 | #define TINYMT32_MUL (1.0f / 16777216.0f) | |||
28 | ||||
29 | #if defined(__cplusplus) | |||
30 | extern "C" { | |||
31 | #endif | |||
32 | ||||
33 | /** | |||
34 | * tinymt32 internal state vector and parameters | |||
35 | */ | |||
36 | struct TINYMT32_T { | |||
37 | uint32_t status[4]; | |||
38 | uint32_t mat1; | |||
39 | uint32_t mat2; | |||
40 | uint32_t tmat; | |||
41 | }; | |||
42 | ||||
43 | typedef struct TINYMT32_T tinymt32_t; | |||
44 | ||||
45 | void tinymt32_init(tinymt32_t * random, uint32_t seed); | |||
46 | void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[], | |||
47 | int key_length); | |||
48 | ||||
49 | #if defined(__GNUC__) | |||
50 | /** | |||
51 | * This function always returns 127 | |||
52 | * @param random not used | |||
53 | * @return always 127 | |||
54 | */ | |||
55 | inline static int tinymt32_get_mexp( | |||
56 | tinymt32_t * random __attribute__((unused))) { | |||
57 | return TINYMT32_MEXP; | |||
58 | } | |||
59 | #else | |||
60 | inline static int tinymt32_get_mexp(tinymt32_t * random) { | |||
61 | return TINYMT32_MEXP; | |||
62 | } | |||
63 | #endif | |||
64 | ||||
65 | /** | |||
66 | * This function changes internal state of tinymt32. | |||
67 | * Users should not call this function directly. | |||
68 | * @param random tinymt internal status | |||
69 | */ | |||
70 | 18985 | inline static void tinymt32_next_state(tinymt32_t * random) { | ||
71 | uint32_t x; | |||
72 | uint32_t y; | |||
73 | ||||
74 | 18985 | y = random->status[3]; | ||
75 | 18985 | x = (random->status[0] & TINYMT32_MASK) | ||
76 | 18985 | ^ random->status[1] | ||
77 | 18985 | ^ random->status[2]; | ||
78 | 18985 | x ^= (x << TINYMT32_SH0); | ||
79 | 18985 | y ^= (y >> TINYMT32_SH0) ^ x; | ||
80 | 18985 | random->status[0] = random->status[1]; | ||
81 | 18985 | random->status[1] = random->status[2]; | ||
82 | 18985 | random->status[2] = x ^ (y << TINYMT32_SH1); | ||
83 | 18985 | random->status[3] = y; | ||
84 | 18985 | int32_t const a = -((int32_t)(y & 1)) & (int32_t)random->mat1; | ||
85 | 18985 | int32_t const b = -((int32_t)(y & 1)) & (int32_t)random->mat2; | ||
86 | 18985 | random->status[1] ^= (uint32_t)a; | ||
87 | 18985 | random->status[2] ^= (uint32_t)b; | ||
88 | 18985 | } | ||
89 | ||||
90 | /** | |||
91 | * This function outputs 32-bit unsigned integer from internal state. | |||
92 | * Users should not call this function directly. | |||
93 | * @param random tinymt internal status | |||
94 | * @return 32-bit unsigned pseudorandom number | |||
95 | */ | |||
96 | 1001 | inline static uint32_t tinymt32_temper(tinymt32_t * random) { | ||
97 | uint32_t t0, t1; | |||
98 | 1001 | t0 = random->status[3]; | ||
99 | #if defined(LINEARITY_CHECK) | |||
100 | t1 = random->status[0] | |||
101 | ^ (random->status[2] >> TINYMT32_SH8); | |||
102 | #else | |||
103 | 1001 | t1 = random->status[0] | ||
104 | 1001 | + (random->status[2] >> TINYMT32_SH8); | ||
105 | #endif | |||
106 | 1001 | t0 ^= t1; | ||
107 |
2/2✓ Branch 0 taken 563 times.
✓ Branch 1 taken 438 times.
|
2/2✓ Decision 'true' taken 563 times.
✓ Decision 'false' taken 438 times.
|
1001 | if ((t1 & 1) != 0) { |
108 | 563 | t0 ^= random->tmat; | ||
109 | } | |||
110 | 1001 | return t0; | ||
111 | } | |||
112 | ||||
113 | /** | |||
114 | * This function outputs floating point number from internal state. | |||
115 | * Users should not call this function directly. | |||
116 | * @param random tinymt internal status | |||
117 | * @return floating point number r (1.0 <= r < 2.0) | |||
118 | */ | |||
119 | inline static float tinymt32_temper_conv(tinymt32_t * random) { | |||
120 | uint32_t t0, t1; | |||
121 | union { | |||
122 | uint32_t u; | |||
123 | float f; | |||
124 | } conv; | |||
125 | ||||
126 | t0 = random->status[3]; | |||
127 | #if defined(LINEARITY_CHECK) | |||
128 | t1 = random->status[0] | |||
129 | ^ (random->status[2] >> TINYMT32_SH8); | |||
130 | #else | |||
131 | t1 = random->status[0] | |||
132 | + (random->status[2] >> TINYMT32_SH8); | |||
133 | #endif | |||
134 | t0 ^= t1; | |||
135 | if ((t1 & 1) != 0) { | |||
136 | conv.u = ((t0 ^ random->tmat) >> 9) | UINT32_C(0x3f800000); | |||
137 | } else { | |||
138 | conv.u = (t0 >> 9) | UINT32_C(0x3f800000); | |||
139 | } | |||
140 | return conv.f; | |||
141 | } | |||
142 | ||||
143 | /** | |||
144 | * This function outputs floating point number from internal state. | |||
145 | * Users should not call this function directly. | |||
146 | * @param random tinymt internal status | |||
147 | * @return floating point number r (1.0 < r < 2.0) | |||
148 | */ | |||
149 | inline static float tinymt32_temper_conv_open(tinymt32_t * random) { | |||
150 | uint32_t t0, t1; | |||
151 | union { | |||
152 | uint32_t u; | |||
153 | float f; | |||
154 | } conv; | |||
155 | ||||
156 | t0 = random->status[3]; | |||
157 | #if defined(LINEARITY_CHECK) | |||
158 | t1 = random->status[0] | |||
159 | ^ (random->status[2] >> TINYMT32_SH8); | |||
160 | #else | |||
161 | t1 = random->status[0] | |||
162 | + (random->status[2] >> TINYMT32_SH8); | |||
163 | #endif | |||
164 | t0 ^= t1; | |||
165 | if ((t1 & 1) != 0) { | |||
166 | conv.u = ((t0 ^ random->tmat) >> 9) | UINT32_C(0x3f800001); | |||
167 | } else { | |||
168 | conv.u = (t0 >> 9) | UINT32_C(0x3f800001); | |||
169 | } | |||
170 | return conv.f; | |||
171 | } | |||
172 | ||||
173 | /** | |||
174 | * This function outputs 32-bit unsigned integer from internal state. | |||
175 | * @param random tinymt internal status | |||
176 | * @return 32-bit unsigned integer r (0 <= r < 2^32) | |||
177 | */ | |||
178 | inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) { | |||
179 | tinymt32_next_state(random); | |||
180 | return tinymt32_temper(random); | |||
181 | } | |||
182 | ||||
183 | /** | |||
184 | * This function outputs floating point number from internal state. | |||
185 | * This function is implemented using multiplying by (1 / 2^24). | |||
186 | * floating point multiplication is faster than using union trick in | |||
187 | * my Intel CPU. | |||
188 | * @param random tinymt internal status | |||
189 | * @return floating point number r (0.0 <= r < 1.0) | |||
190 | */ | |||
191 | 1001 | inline static float tinymt32_generate_float(tinymt32_t * random) { | ||
192 | 1001 | tinymt32_next_state(random); | ||
193 | 1001 | return (float)(tinymt32_temper(random) >> 8) * TINYMT32_MUL; | ||
194 | } | |||
195 | ||||
196 | /** | |||
197 | * This function outputs floating point number from internal state. | |||
198 | * This function is implemented using union trick. | |||
199 | * @param random tinymt internal status | |||
200 | * @return floating point number r (1.0 <= r < 2.0) | |||
201 | */ | |||
202 | inline static float tinymt32_generate_float12(tinymt32_t * random) { | |||
203 | tinymt32_next_state(random); | |||
204 | return tinymt32_temper_conv(random); | |||
205 | } | |||
206 | ||||
207 | /** | |||
208 | * This function outputs floating point number from internal state. | |||
209 | * This function is implemented using union trick. | |||
210 | * @param random tinymt internal status | |||
211 | * @return floating point number r (0.0 <= r < 1.0) | |||
212 | */ | |||
213 | inline static float tinymt32_generate_float01(tinymt32_t * random) { | |||
214 | tinymt32_next_state(random); | |||
215 | return tinymt32_temper_conv(random) - 1.0f; | |||
216 | } | |||
217 | ||||
218 | /** | |||
219 | * This function outputs floating point number from internal state. | |||
220 | * This function may return 1.0 and never returns 0.0. | |||
221 | * @param random tinymt internal status | |||
222 | * @return floating point number r (0.0 < r <= 1.0) | |||
223 | */ | |||
224 | inline static float tinymt32_generate_floatOC(tinymt32_t * random) { | |||
225 | tinymt32_next_state(random); | |||
226 | return 1.0f - tinymt32_generate_float(random); | |||
227 | } | |||
228 | ||||
229 | /** | |||
230 | * This function outputs floating point number from internal state. | |||
231 | * This function returns neither 0.0 nor 1.0. | |||
232 | * @param random tinymt internal status | |||
233 | * @return floating point number r (0.0 < r < 1.0) | |||
234 | */ | |||
235 | inline static float tinymt32_generate_floatOO(tinymt32_t * random) { | |||
236 | tinymt32_next_state(random); | |||
237 | return tinymt32_temper_conv_open(random) - 1.0f; | |||
238 | } | |||
239 | ||||
240 | /** | |||
241 | * This function outputs double precision floating point number from | |||
242 | * internal state. The returned value has 32-bit precision. | |||
243 | * In other words, this function makes one double precision floating point | |||
244 | * number from one 32-bit unsigned integer. | |||
245 | * @param random tinymt internal status | |||
246 | * @return floating point number r (0.0 <= r < 1.0) | |||
247 | */ | |||
248 | inline static double tinymt32_generate_32double(tinymt32_t * random) { | |||
249 | tinymt32_next_state(random); | |||
250 | return tinymt32_temper(random) * (1.0 / 4294967296.0); | |||
251 | } | |||
252 | ||||
253 | #if defined(__cplusplus) | |||
254 | } | |||
255 | #endif | |||
256 | ||||
257 | #endif | |||
258 |