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