source: Sophya/trunk/SophyaLib/BaseTools/tinymt32.h@ 4040

Last change on this file since 4040 was 4019, checked in by cmv, 14 years ago

ajout generateurs tinymt32+64, cmv 24/09/2011

File size: 6.8 KB
Line 
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 / 4294967296.0f)
28
29/**
30 * tinymt32 internal state vector and parameters
31 */
32struct TINYMT32_T {
33 uint32_t status[4];
34 uint32_t mat1;
35 uint32_t mat2;
36 uint32_t tmat;
37};
38
39typedef struct TINYMT32_T tinymt32_t;
40
41/* --- Ajout par cmv / Compilation C++ --- */
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46void tinymt32_init(tinymt32_t * random, uint32_t seed);
47void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[],
48 int key_length);
49
50/* --- Ajout par cmv / Compilation C++ --- */
51#ifdef __cplusplus
52}
53#endif
54
55#if defined(__GNUC__)
56/**
57 * This function always returns 127
58 * @param random not used
59 * @return always 127
60 */
61inline static int tinymt32_get_mexp(
62 tinymt32_t * random __attribute__((unused))) {
63 return TINYMT32_MEXP;
64}
65#else
66inline static int tinymt32_get_mexp(tinymt32_t * random) {
67 return TINYMT32_MEXP;
68}
69#endif
70
71/**
72 * This function changes internal state of tinymt32.
73 * Users should not call this function directly.
74 * @param random tinymt internal status
75 */
76inline static void tinymt32_next_state(tinymt32_t * random) {
77 uint32_t x;
78 uint32_t y;
79
80 y = random->status[3];
81 x = (random->status[0] & TINYMT32_MASK)
82 ^ random->status[1]
83 ^ random->status[2];
84 x ^= (x << TINYMT32_SH0);
85 y ^= (y >> TINYMT32_SH0) ^ x;
86 random->status[0] = random->status[1];
87 random->status[1] = random->status[2];
88 random->status[2] = x ^ (y << TINYMT32_SH1);
89 random->status[3] = y;
90 random->status[1] ^= -((int32_t)(y & 1)) & random->mat1;
91 random->status[2] ^= -((int32_t)(y & 1)) & random->mat2;
92}
93
94/**
95 * This function outputs 32-bit unsigned integer from internal state.
96 * Users should not call this function directly.
97 * @param random tinymt internal status
98 * @return 32-bit unsigned pseudorandom number
99 */
100inline static uint32_t tinymt32_temper(tinymt32_t * random) {
101 uint32_t t0, t1;
102 t0 = random->status[3];
103#if defined(LINEARITY_CHECK)
104 t1 = random->status[0]
105 ^ (random->status[2] >> TINYMT32_SH8);
106#else
107 t1 = random->status[0]
108 + (random->status[2] >> TINYMT32_SH8);
109#endif
110 t0 ^= t1;
111 t0 ^= -((int32_t)(t1 & 1)) & random->tmat;
112 return t0;
113}
114
115/**
116 * This function outputs floating point number from internal state.
117 * Users should not call this function directly.
118 * @param random tinymt internal status
119 * @return floating point number r (1.0 <= r < 2.0)
120 */
121inline static float tinymt32_temper_conv(tinymt32_t * random) {
122 uint32_t t0, t1;
123 union {
124 uint32_t u;
125 float f;
126 } conv;
127
128 t0 = random->status[3];
129#if defined(LINEARITY_CHECK)
130 t1 = random->status[0]
131 ^ (random->status[2] >> TINYMT32_SH8);
132#else
133 t1 = random->status[0]
134 + (random->status[2] >> TINYMT32_SH8);
135#endif
136 t0 ^= t1;
137 conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9)
138 | UINT32_C(0x3f800000);
139 return conv.f;
140}
141
142/**
143 * This function outputs floating point number from internal state.
144 * Users should not call this function directly.
145 * @param random tinymt internal status
146 * @return floating point number r (1.0 < r < 2.0)
147 */
148inline static float tinymt32_temper_conv_open(tinymt32_t * random) {
149 uint32_t t0, t1;
150 union {
151 uint32_t u;
152 float f;
153 } conv;
154
155 t0 = random->status[3];
156#if defined(LINEARITY_CHECK)
157 t1 = random->status[0]
158 ^ (random->status[2] >> TINYMT32_SH8);
159#else
160 t1 = random->status[0]
161 + (random->status[2] >> TINYMT32_SH8);
162#endif
163 t0 ^= t1;
164 conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9)
165 | UINT32_C(0x3f800001);
166 return conv.f;
167}
168
169/**
170 * This function outputs 32-bit unsigned integer from internal state.
171 * @param random tinymt internal status
172 * @return 32-bit unsigned integer r (0 <= r < 2^32)
173 */
174inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) {
175 tinymt32_next_state(random);
176 return tinymt32_temper(random);
177}
178
179/**
180 * This function outputs floating point number from internal state.
181 * This function is implemented using multiplying by 1 / 2^32.
182 * floating point multiplication is faster than using union trick in
183 * my Intel CPU.
184 * @param random tinymt internal status
185 * @return floating point number r (0.0 <= r < 1.0)
186 */
187inline static float tinymt32_generate_float(tinymt32_t * random) {
188 tinymt32_next_state(random);
189 return tinymt32_temper(random) * TINYMT32_MUL;
190}
191
192/**
193 * This function outputs floating point number from internal state.
194 * This function is implemented using union trick.
195 * @param random tinymt internal status
196 * @return floating point number r (1.0 <= r < 2.0)
197 */
198inline static float tinymt32_generate_float12(tinymt32_t * random) {
199 tinymt32_next_state(random);
200 return tinymt32_temper_conv(random);
201}
202
203/**
204 * This function outputs floating point number from internal state.
205 * This function is implemented using union trick.
206 * @param random tinymt internal status
207 * @return floating point number r (0.0 <= r < 1.0)
208 */
209inline static float tinymt32_generate_float01(tinymt32_t * random) {
210 tinymt32_next_state(random);
211 return tinymt32_temper_conv(random) - 1.0f;
212}
213
214/**
215 * This function outputs floating point number from internal state.
216 * This function may return 1.0 and never returns 0.0.
217 * @param random tinymt internal status
218 * @return floating point number r (0.0 < r <= 1.0)
219 */
220inline static float tinymt32_generate_floatOC(tinymt32_t * random) {
221 tinymt32_next_state(random);
222 return 1.0f - tinymt32_generate_float(random);
223}
224
225/**
226 * This function outputs floating point number from internal state.
227 * This function returns neither 0.0 nor 1.0.
228 * @param random tinymt internal status
229 * @return floating point number r (0.0 < r < 0.0)
230 */
231inline static float tinymt32_generate_floatOO(tinymt32_t * random) {
232 tinymt32_next_state(random);
233 return tinymt32_temper_conv_open(random) - 1.0f;
234}
235
236/**
237 * This function outputs double precision floating point number from
238 * internal state. The returned value has 32-bit precision.
239 * In other words, this function makes one double precision floating point
240 * number from one 32-bit unsigned integer.
241 * @param random tinymt internal status
242 * @return floating point number r (1.0 < r < 2.0)
243 */
244inline static double tinymt32_generate_32double(tinymt32_t * random) {
245 tinymt32_next_state(random);
246 return tinymt32_temper(random) * (1.0 / 4294967296.0);
247}
248#endif
Note: See TracBrowser for help on using the repository browser.