dbf-halloween2015

view src/rng.cc @ 0:50683c78264e

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