naev 0.11.5
rng.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
12#include <errno.h>
13#include <math.h>
14#include <stdint.h>
15#include <time.h>
16#include <unistd.h>
17#include "SDL.h"
18
19#include "naev.h"
20
21#if HAS_POSIX
22#include <fcntl.h>
23#include <sys/time.h>
24#endif /* HAS_POSIX */
25#if __WIN32__
26#include <sys/timeb.h>
27#include <sys/types.h>
28#endif /* __WIN32__ */
31#include "rng.h"
32
33#include "log.h"
34
35/*
36 * mersenne twister state
37 */
38static uint32_t MT[624];
39static uint32_t mt_y;
40static int mt_pos = 0;
42/*
43 * prototypes
44 */
45static uint32_t rng_timeEntropy (void);
46/* mersenne twister */
47static void mt_initArray( uint32_t seed );
48static void mt_genArray (void);
49static uint32_t mt_getInt (void);
50
56void rng_init (void)
57{
58 uint32_t i;
59 int need_init;
60
61 need_init = 1; /* initialize by default */
62#if __LINUX__
63 int fd;
64 fd = open("/dev/urandom", O_RDONLY); /* /dev/urandom is better than time seed */
65 if (fd != -1) {
66 i = sizeof(uint32_t)*624;
67 if (read( fd, &MT, i ) == (ssize_t)i)
68 need_init = 0;
69 else
70 i = rng_timeEntropy();
71 close(fd);
72 }
73 else
74 i = rng_timeEntropy();
75#else /* __LINUX__ */
76 i = rng_timeEntropy();
77#endif /* __LINUX__ */
78
79 if (need_init)
80 mt_initArray( i );
81 for (i=0; i<10; i++) /* generate numbers to get away from poor initial values */
83}
84
92static uint32_t rng_timeEntropy (void)
93{
94 int i;
95#if HAS_POSIX
96 struct timeval tv;
97 gettimeofday( &tv, NULL );
98 i = tv.tv_sec * 1000000 + tv.tv_usec;
99#elif __WIN32__
100 struct _timeb tb;
101 _ftime( &tb );
102 i = tb.time * 1000 + tb.millitm;
103#else
104#error "Feature needs implementation on this Operating System for Naev to work."
105#endif
106 return i;
107}
108
114static void mt_initArray( uint32_t seed )
115{
116 MT[0] = seed;
117 for (int i=1; i<624; i++)
118 MT[i] = 1812433253 * (MT[i-1] ^ (((MT[i-1])) + i) >> 30);
119 mt_pos = 0;
120}
121
127static void mt_genArray (void)
128{
129 for (int i=0; i<624; i++ ) {
130 mt_y = (MT[i] & 0x80000000) + ((MT[i] % 624) & 0x7FFFFFFF);
131 if (mt_y % 2) /* odd */
132 MT[i] = (MT[(i+397) % 624] ^ (mt_y >> 1)) ^ 2567483615U;
133 else /* even */
134 MT[i] = MT[(i+397) % 624] ^ (mt_y >> 1);
135 }
136 mt_pos = 0;
137}
138
146static uint32_t mt_getInt (void)
147{
148 if (mt_pos >= 624)
149 mt_genArray();
150
151 mt_y = MT[mt_pos++];
152 mt_y ^= mt_y >> 11;
153 mt_y ^= (mt_y << 7) & 2636928640U;
154 mt_y ^= (mt_y << 15) & 4022730752U;
155 mt_y ^= mt_y >> 18;
156
157 return mt_y;
158}
159
167unsigned int randint (void)
168{
169 return mt_getInt();
170}
171
179static double m_div = (double)(0xFFFFFFFF);
180double randfp (void)
181{
182 double m = (double)mt_getInt();
183 return m / m_div;
184}
185
203double Normal( double x )
204{
205 double t;
206 double series;
207 const double b1 = 0.319381530;
208 const double b2 = -0.356563782;
209 const double b3 = 1.781477937;
210 const double b4 = -1.821255978;
211 const double b5 = 1.330274429;
212 const double p = 0.2316419;
213 const double c = 0.39894228;
214
215 t = 1. / ( 1. + p * FABS(x) );
216 series = (1. - c * exp( -x * x / 2. ) * t *
217 ( t *( t * ( t * ( t * b5 + b4 ) + b3 ) + b2 ) + b1 ));
218 return (x > 0.) ? 1. - series : series;
219}
220
246/* Coefficients in rational approximations. */
247static const double a[] =
248{
249 -3.969683028665376e+01,
250 2.209460984245205e+02,
251 -2.759285104469687e+02,
252 1.383577518672690e+02,
253 -3.066479806614716e+01,
254 2.506628277459239e+00
255};
256static const double b[] =
257{
258 -5.447609879822406e+01,
259 1.615858368580409e+02,
260 -1.556989798598866e+02,
261 6.680131188771972e+01,
262 -1.328068155288572e+01
263};
264static const double c[] =
265{
266 -7.784894002430293e-03,
267 -3.223964580411365e-01,
268 -2.400758277161838e+00,
269 -2.549732539343734e+00,
270 4.374664141464968e+00,
271 2.938163982698783e+00
272};
273static const double d[] =
274{
275 7.784695709041462e-03,
276 3.224671290700398e-01,
277 2.445134137142996e+00,
278 3.754408661907416e+00
279};
280#define LOW 0.02425
281#define HIGH 0.97575
282double NormalInverse( double p )
283{
284 double x, e, u, q, r;
285
286 /* Check for errors */
287 errno = 0;
288 if ((p < 0) || (p > 1)) {
289 errno = EDOM;
290 return 0.;
291 }
292 else if (p == 0.) {
293 errno = ERANGE;
294 return -HUGE_VAL /* minus "infinity" */;
295 }
296 else if (p == 1.) {
297 errno = ERANGE;
298 return HUGE_VAL /* "infinity" */;
299 }
300 /* Use different approximations for different parts */
301 else if (p < LOW) {
302 /* Rational approximation for lower region */
303 q = sqrt(-2*log(p));
304 x = (((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
305 ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
306 }
307 else if (p > HIGH) {
308 /* Rational approximation for upper region */
309 q = sqrt(-2*log(1-p));
310 x = -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
311 ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
312 }
313 else {
314 /* Rational approximation for central region */
315 q = p - 0.5;
316 r = q*q;
317 x = (((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q /
318 (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1);
319 }
320
321 /* Full machine precision */
322 e = 0.5 * erfc(-x / M_SQRT2) - p;
323 u = e * 2.5066282746310002 /* sqrt(2*pi) */ * exp((x*x)/2);
324 x = x - u/(1 + x*u/2);
325
326 return x;
327}
Header file with generic functions and naev-specifics.
#define FABS(x)
Definition naev.h:37
static const double c[]
Definition rng.c:264
static void mt_initArray(uint32_t seed)
Generates the initial mersenne twister based on seed.
Definition rng.c:114
double Normal(double x)
Calculates the Normal distribution.
Definition rng.c:203
#define HIGH
Definition rng.c:281
static const double d[]
Definition rng.c:273
static int mt_pos
Definition rng.c:40
double randfp(void)
Gets a random float between 0 and 1 (inclusive).
Definition rng.c:180
static uint32_t mt_y
Definition rng.c:39
static uint32_t mt_getInt(void)
Gets the next int.
Definition rng.c:146
double NormalInverse(double p)
Calculates the inverse of the normal.
Definition rng.c:282
#define LOW
Definition rng.c:280
static double m_div
Definition rng.c:179
void rng_init(void)
Initializes the random subsystem.
Definition rng.c:56
static void mt_genArray(void)
Generates a new set of random numbers for the mersenne twister.
Definition rng.c:127
unsigned int randint(void)
Gets a random integer.
Definition rng.c:167
static uint32_t MT[624]
Definition rng.c:38
static uint32_t rng_timeEntropy(void)
Uses time as a source of entropy.
Definition rng.c:92