-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrandom.c
166 lines (148 loc) · 3.32 KB
/
random.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* random.c -- Random number generator
Copyright (C) 2003 Robin Hogan <[email protected]> */
#include <stdlib.h>
#include <math.h>
#include "random.h"
static FILE *dev_random = NULL;
/* This is essentially the "ran2" function from "Numerical Recipies"
(Press et al. 1988). It has been split into two functions, one to
seed and the other to fetch the next value */
#define M 714025
#define IA 1366
#define IC 150889
static long iy, ir[98];
static int iff = 0;
static long idum;
void
seed_random_number_generator(long seed)
{
int j;
iff = 1;
if ((seed=(IC-seed) % M) < 0)
seed = -seed;
for (j = 1; j <= 97; j++) {
seed = (IA*seed+IC) % M;
ir[j] = seed;
}
iy = (IA*seed+IC) % M;
idum = seed;
}
static
float
nr_uniform_deviate(void)
{
int j;
if (iff == 0) {
seed_random_number_generator(-1);
}
j = 1 + 97.0*iy/M;
if (j > 97 || j < 1) {
fprintf(stderr, "Error in random number generator\n");
exit(1);
}
iy = ir[j];
idum = (IA*idum+IC) % M;
ir[j] = idum;
return (float) iy/M;
}
/* By default we use the nr_uniform_deviate function */
float (*uniform_deviate) (void) = *nr_uniform_deviate;
/* Recent versions of linux provide two devices, /dev/random and
/dev/urandom. The first provides a source of high quality random
numbers derived from interrupt timings. The second provides lower
quality random numbers using interrupt timings when available and a
more standard algorithm if not - this is much faster. Use the
set_kernel_random_file() function to set the file to use. */
static
float
kernel_uniform_deviate(void)
{
unsigned short value;
fread(&value, 2, 1, dev_random);
return ((float) value)/65536.0;
}
int
kernel_int_seed(void)
{
int value;
if (dev_random) {
fread(&value, sizeof(int), 1, dev_random);
return value;
}
else {
return 1;
}
}
FILE *
open_kernel_random_file(char *file_name)
{
dev_random = fopen(file_name, "r");
if (dev_random) {
uniform_deviate = kernel_uniform_deviate;
}
return dev_random;
}
void
close_kernel_random_file(void)
{
if (dev_random) {
fclose(dev_random);
}
uniform_deviate = nr_uniform_deviate;
}
/* Calculate Gaussian deviates from uniform deviates - this is the
"gasdev" function from Numerical Recipies */
float
gaussian_deviate(void)
{
static int iset = 0;
static float gset;
float fac, r, v1, v2;
if (iset == 0) {
do {
v1 = 2.0 * uniform_deviate() - 1.0;
v2 = 2.0 * uniform_deviate() - 1.0;
r = v1*v1 + v2*v2;
}
while (r >= 1.0 || r == 0.0);
fac = sqrt(-2.0*log(r)/r);
gset = v1*fac;
iset = 1;
return v2*fac;
}
else {
iset = 0;
return gset;
}
}
/* A function for generating 32 random bits */
unsigned int
bitfield32_deviate(void)
{
static long ix1 = 1;
static long ix2 = 1;
unsigned long r;
ix1 = (3877*ix1 + 29573) % 139968;
ix2 = (8121*ix2 + 28411) % 134456;
r = ix1*(65535.0/(139968-1.0));
return r*65535;/* + ix2*(65535.0/(134456-1.0)); */
}
/* */
unsigned int
hash_32(int n, unsigned char *sequence, unsigned int hash)
{
int i;
for (i = 0; i < n; ++i) {
hash = FNV_32_HASH(hash, sequence[i]);
}
return hash;
}
unsigned int
seeded_uniform_deviates(int n, float *target, unsigned int seed)
{
int i;
for (i = 0; i < n; ++i) {
target[i] = (float) (seed = (IA*seed+IC) % M)/M;
}
return seed;
}