CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/sfmt19937/SFMT.h
Views: 1401
1
#pragma once
2
/**
3
* @file SFMT.h
4
*
5
* @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom
6
* number generator using C structure.
7
*
8
* @author Mutsuo Saito (Hiroshima University)
9
* @author Makoto Matsumoto (The University of Tokyo)
10
*
11
* Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
12
* University.
13
* Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima
14
* University and The University of Tokyo.
15
* All rights reserved.
16
*
17
* The 3-clause BSD License is applied to this software, see
18
* LICENSE.txt
19
*
20
* @note We assume that your system has inttypes.h. If your system
21
* doesn't have inttypes.h, you have to typedef uint32_t and uint64_t,
22
* and you have to define PRIu64 and PRIx64 in this file as follows:
23
* @verbatim
24
typedef unsigned int uint32_t
25
typedef unsigned long long uint64_t
26
#define PRIu64 "llu"
27
#define PRIx64 "llx"
28
@endverbatim
29
* uint32_t must be exactly 32-bit unsigned integer type (no more, no
30
* less), and uint64_t must be exactly 64-bit unsigned integer type.
31
* PRIu64 and PRIx64 are used for printf function to print 64-bit
32
* unsigned int and 64-bit unsigned int in hexadecimal format.
33
*/
34
35
#ifndef SFMTST_H
36
#define SFMTST_H
37
#if defined(__cplusplus)
38
extern "C" {
39
#endif
40
41
#include <stdio.h>
42
#include <assert.h>
43
44
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
45
#include <inttypes.h>
46
#elif defined(_MSC_VER) || defined(__BORLANDC__)
47
typedef unsigned int uint32_t;
48
typedef unsigned __int64 uint64_t;
49
#if !defined(__cplusplus)
50
#define inline __inline
51
#endif
52
#else
53
#include <inttypes.h>
54
#if defined(__GNUC__)
55
#define inline __inline__
56
#endif
57
#endif
58
59
#ifndef PRIu64
60
#if defined(_MSC_VER) || defined(__BORLANDC__)
61
#define PRIu64 "I64u"
62
#define PRIx64 "I64x"
63
#else
64
#define PRIu64 "llu"
65
#define PRIx64 "llx"
66
#endif
67
#endif
68
69
#include "SFMT-params.h"
70
71
/*------------------------------------------
72
128-bit SIMD like data type for standard C
73
------------------------------------------*/
74
#if defined(HAVE_ALTIVEC)
75
#if !defined(__APPLE__)
76
#include <altivec.h>
77
#endif
78
/** 128-bit data structure */
79
union W128_T {
80
vector unsigned int s;
81
uint32_t u[4];
82
uint64_t u64[2];
83
};
84
#elif defined(HAVE_SSE2)
85
#include <emmintrin.h>
86
87
/** 128-bit data structure */
88
union W128_T {
89
uint32_t u[4];
90
uint64_t u64[2];
91
__m128i si;
92
};
93
#else
94
/** 128-bit data structure */
95
union W128_T {
96
uint32_t u[4];
97
uint64_t u64[2];
98
};
99
#endif
100
101
/** 128-bit data type */
102
typedef union W128_T w128_t;
103
104
/**
105
* SFMT internal state
106
*/
107
struct SFMT_T {
108
/** the 128-bit internal state array */
109
w128_t state[SFMT_N];
110
/** index counter to the 32-bit internal state array */
111
int idx;
112
};
113
114
typedef struct SFMT_T sfmt_t;
115
116
void sfmt_fill_array32(sfmt_t * sfmt, uint32_t * array, int size);
117
void sfmt_fill_array64(sfmt_t * sfmt, uint64_t * array, int size);
118
void sfmt_init_gen_rand(sfmt_t * sfmt, uint32_t seed);
119
void sfmt_init_by_array(sfmt_t * sfmt, uint32_t * init_key, int key_length);
120
const char * sfmt_get_idstring(sfmt_t * sfmt);
121
int sfmt_get_min_array_size32(sfmt_t * sfmt);
122
int sfmt_get_min_array_size64(sfmt_t * sfmt);
123
void sfmt_gen_rand_all(sfmt_t * sfmt);
124
125
#ifndef ONLY64
126
/**
127
* This function generates and returns 32-bit pseudorandom number.
128
* init_gen_rand or init_by_array must be called before this function.
129
* @param sfmt SFMT internal state
130
* @return 32-bit pseudorandom number
131
*/
132
inline static uint32_t sfmt_genrand_uint32(sfmt_t * sfmt) {
133
uint32_t r;
134
uint32_t * psfmt32 = &sfmt->state[0].u[0];
135
136
if (sfmt->idx >= SFMT_N32) {
137
sfmt_gen_rand_all(sfmt);
138
sfmt->idx = 0;
139
}
140
r = psfmt32[sfmt->idx++];
141
return r;
142
}
143
#endif
144
/**
145
* This function generates and returns 64-bit pseudorandom number.
146
* init_gen_rand or init_by_array must be called before this function.
147
* The function gen_rand64 should not be called after gen_rand32,
148
* unless an initialization is again executed.
149
* @param sfmt SFMT internal state
150
* @return 64-bit pseudorandom number
151
*/
152
inline static uint64_t sfmt_genrand_uint64(sfmt_t * sfmt) {
153
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
154
uint32_t * psfmt32 = &sfmt->state[0].u[0];
155
uint32_t r1, r2;
156
#else
157
uint64_t r;
158
#endif
159
uint64_t * psfmt64 = &sfmt->state[0].u64[0];
160
assert(sfmt->idx % 2 == 0);
161
162
if (sfmt->idx >= SFMT_N32) {
163
sfmt_gen_rand_all(sfmt);
164
sfmt->idx = 0;
165
}
166
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
167
r1 = psfmt32[sfmt->idx];
168
r2 = psfmt32[sfmt->idx + 1];
169
sfmt->idx += 2;
170
return ((uint64_t)r2 << 32) | r1;
171
#else
172
r = psfmt64[sfmt->idx / 2];
173
sfmt->idx += 2;
174
return r;
175
#endif
176
}
177
178
/* =================================================
179
The following real versions are due to Isaku Wada
180
================================================= */
181
/**
182
* converts an unsigned 32-bit number to a double on [0,1]-real-interval.
183
* @param v 32-bit unsigned integer
184
* @return double on [0,1]-real-interval
185
*/
186
inline static double sfmt_to_real1(uint32_t v)
187
{
188
return v * (1.0/4294967295.0);
189
/* divided by 2^32-1 */
190
}
191
192
/**
193
* generates a random number on [0,1]-real-interval
194
* @param sfmt SFMT internal state
195
* @return double on [0,1]-real-interval
196
*/
197
inline static double sfmt_genrand_real1(sfmt_t * sfmt)
198
{
199
return sfmt_to_real1(sfmt_genrand_uint32(sfmt));
200
}
201
202
/**
203
* converts an unsigned 32-bit integer to a double on [0,1)-real-interval.
204
* @param v 32-bit unsigned integer
205
* @return double on [0,1)-real-interval
206
*/
207
inline static double sfmt_to_real2(uint32_t v)
208
{
209
return v * (1.0/4294967296.0);
210
/* divided by 2^32 */
211
}
212
213
/**
214
* generates a random number on [0,1)-real-interval
215
* @param sfmt SFMT internal state
216
* @return double on [0,1)-real-interval
217
*/
218
inline static double sfmt_genrand_real2(sfmt_t * sfmt)
219
{
220
return sfmt_to_real2(sfmt_genrand_uint32(sfmt));
221
}
222
223
/**
224
* converts an unsigned 32-bit integer to a double on (0,1)-real-interval.
225
* @param v 32-bit unsigned integer
226
* @return double on (0,1)-real-interval
227
*/
228
inline static double sfmt_to_real3(uint32_t v)
229
{
230
return (((double)v) + 0.5)*(1.0/4294967296.0);
231
/* divided by 2^32 */
232
}
233
234
/**
235
* generates a random number on (0,1)-real-interval
236
* @param sfmt SFMT internal state
237
* @return double on (0,1)-real-interval
238
*/
239
inline static double sfmt_genrand_real3(sfmt_t * sfmt)
240
{
241
return sfmt_to_real3(sfmt_genrand_uint32(sfmt));
242
}
243
244
/**
245
* converts an unsigned 32-bit integer to double on [0,1)
246
* with 53-bit resolution.
247
* @param v 32-bit unsigned integer
248
* @return double on [0,1)-real-interval with 53-bit resolution.
249
*/
250
inline static double sfmt_to_res53(uint64_t v)
251
{
252
return v * (1.0/18446744073709551616.0);
253
}
254
255
/**
256
* generates a random number on [0,1) with 53-bit resolution
257
* @param sfmt SFMT internal state
258
* @return double on [0,1) with 53-bit resolution
259
*/
260
inline static double sfmt_genrand_res53(sfmt_t * sfmt)
261
{
262
return sfmt_to_res53(sfmt_genrand_uint64(sfmt));
263
}
264
265
266
/* =================================================
267
The following function are added by Saito.
268
================================================= */
269
/**
270
* generates a random number on [0,1) with 53-bit resolution from two
271
* 32 bit integers
272
*/
273
inline static double sfmt_to_res53_mix(uint32_t x, uint32_t y)
274
{
275
return sfmt_to_res53(x | ((uint64_t)y << 32));
276
}
277
278
/**
279
* generates a random number on [0,1) with 53-bit resolution
280
* using two 32bit integers.
281
* @param sfmt SFMT internal state
282
* @return double on [0,1) with 53-bit resolution
283
*/
284
inline static double sfmt_genrand_res53_mix(sfmt_t * sfmt)
285
{
286
uint32_t x, y;
287
288
x = sfmt_genrand_uint32(sfmt);
289
y = sfmt_genrand_uint32(sfmt);
290
return sfmt_to_res53_mix(x, y);
291
}
292
293
#if defined(__cplusplus)
294
}
295
#endif
296
297
#endif
298
299