Chris@87
|
1 /* Random kit 1.3 */
|
Chris@87
|
2
|
Chris@87
|
3 /*
|
Chris@87
|
4 * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.org)
|
Chris@87
|
5 *
|
Chris@87
|
6 * Permission is hereby granted, free of charge, to any person obtaining a
|
Chris@87
|
7 * copy of this software and associated documentation files (the
|
Chris@87
|
8 * "Software"), to deal in the Software without restriction, including
|
Chris@87
|
9 * without limitation the rights to use, copy, modify, merge, publish,
|
Chris@87
|
10 * distribute, sublicense, and/or sell copies of the Software, and to
|
Chris@87
|
11 * permit persons to whom the Software is furnished to do so, subject to
|
Chris@87
|
12 * the following conditions:
|
Chris@87
|
13 *
|
Chris@87
|
14 * The above copyright notice and this permission notice shall be included
|
Chris@87
|
15 * in all copies or substantial portions of the Software.
|
Chris@87
|
16 *
|
Chris@87
|
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
Chris@87
|
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@87
|
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
Chris@87
|
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
Chris@87
|
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
Chris@87
|
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
Chris@87
|
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@87
|
24 */
|
Chris@87
|
25
|
Chris@87
|
26 /* @(#) $Jeannot: randomkit.h,v 1.24 2005/07/21 22:14:09 js Exp $ */
|
Chris@87
|
27
|
Chris@87
|
28 /*
|
Chris@87
|
29 * Typical use:
|
Chris@87
|
30 *
|
Chris@87
|
31 * {
|
Chris@87
|
32 * rk_state state;
|
Chris@87
|
33 * unsigned long seed = 1, random_value;
|
Chris@87
|
34 *
|
Chris@87
|
35 * rk_seed(seed, &state); // Initialize the RNG
|
Chris@87
|
36 * ...
|
Chris@87
|
37 * random_value = rk_random(&state); // Generate random values in [0..RK_MAX]
|
Chris@87
|
38 * }
|
Chris@87
|
39 *
|
Chris@87
|
40 * Instead of rk_seed, you can use rk_randomseed which will get a random seed
|
Chris@87
|
41 * from /dev/urandom (or the clock, if /dev/urandom is unavailable):
|
Chris@87
|
42 *
|
Chris@87
|
43 * {
|
Chris@87
|
44 * rk_state state;
|
Chris@87
|
45 * unsigned long random_value;
|
Chris@87
|
46 *
|
Chris@87
|
47 * rk_randomseed(&state); // Initialize the RNG with a random seed
|
Chris@87
|
48 * ...
|
Chris@87
|
49 * random_value = rk_random(&state); // Generate random values in [0..RK_MAX]
|
Chris@87
|
50 * }
|
Chris@87
|
51 */
|
Chris@87
|
52
|
Chris@87
|
53 /*
|
Chris@87
|
54 * Useful macro:
|
Chris@87
|
55 * RK_DEV_RANDOM: the device used for random seeding.
|
Chris@87
|
56 * defaults to "/dev/urandom"
|
Chris@87
|
57 */
|
Chris@87
|
58
|
Chris@87
|
59 #include <stddef.h>
|
Chris@87
|
60
|
Chris@87
|
61 #ifndef _RANDOMKIT_
|
Chris@87
|
62 #define _RANDOMKIT_
|
Chris@87
|
63
|
Chris@87
|
64 #define RK_STATE_LEN 624
|
Chris@87
|
65
|
Chris@87
|
66 typedef struct rk_state_
|
Chris@87
|
67 {
|
Chris@87
|
68 unsigned long key[RK_STATE_LEN];
|
Chris@87
|
69 int pos;
|
Chris@87
|
70 int has_gauss; /* !=0: gauss contains a gaussian deviate */
|
Chris@87
|
71 double gauss;
|
Chris@87
|
72
|
Chris@87
|
73 /* The rk_state structure has been extended to store the following
|
Chris@87
|
74 * information for the binomial generator. If the input values of n or p
|
Chris@87
|
75 * are different than nsave and psave, then the other parameters will be
|
Chris@87
|
76 * recomputed. RTK 2005-09-02 */
|
Chris@87
|
77
|
Chris@87
|
78 int has_binomial; /* !=0: following parameters initialized for
|
Chris@87
|
79 binomial */
|
Chris@87
|
80 double psave;
|
Chris@87
|
81 long nsave;
|
Chris@87
|
82 double r;
|
Chris@87
|
83 double q;
|
Chris@87
|
84 double fm;
|
Chris@87
|
85 long m;
|
Chris@87
|
86 double p1;
|
Chris@87
|
87 double xm;
|
Chris@87
|
88 double xl;
|
Chris@87
|
89 double xr;
|
Chris@87
|
90 double c;
|
Chris@87
|
91 double laml;
|
Chris@87
|
92 double lamr;
|
Chris@87
|
93 double p2;
|
Chris@87
|
94 double p3;
|
Chris@87
|
95 double p4;
|
Chris@87
|
96
|
Chris@87
|
97 }
|
Chris@87
|
98 rk_state;
|
Chris@87
|
99
|
Chris@87
|
100 typedef enum {
|
Chris@87
|
101 RK_NOERR = 0, /* no error */
|
Chris@87
|
102 RK_ENODEV = 1, /* no RK_DEV_RANDOM device */
|
Chris@87
|
103 RK_ERR_MAX = 2
|
Chris@87
|
104 } rk_error;
|
Chris@87
|
105
|
Chris@87
|
106 /* error strings */
|
Chris@87
|
107 extern char *rk_strerror[RK_ERR_MAX];
|
Chris@87
|
108
|
Chris@87
|
109 /* Maximum generated random value */
|
Chris@87
|
110 #define RK_MAX 0xFFFFFFFFUL
|
Chris@87
|
111
|
Chris@87
|
112 #ifdef __cplusplus
|
Chris@87
|
113 extern "C" {
|
Chris@87
|
114 #endif
|
Chris@87
|
115
|
Chris@87
|
116 /*
|
Chris@87
|
117 * Initialize the RNG state using the given seed.
|
Chris@87
|
118 */
|
Chris@87
|
119 extern void rk_seed(unsigned long seed, rk_state *state);
|
Chris@87
|
120
|
Chris@87
|
121 /*
|
Chris@87
|
122 * Initialize the RNG state using a random seed.
|
Chris@87
|
123 * Uses /dev/random or, when unavailable, the clock (see randomkit.c).
|
Chris@87
|
124 * Returns RK_NOERR when no errors occurs.
|
Chris@87
|
125 * Returns RK_ENODEV when the use of RK_DEV_RANDOM failed (for example because
|
Chris@87
|
126 * there is no such device). In this case, the RNG was initialized using the
|
Chris@87
|
127 * clock.
|
Chris@87
|
128 */
|
Chris@87
|
129 extern rk_error rk_randomseed(rk_state *state);
|
Chris@87
|
130
|
Chris@87
|
131 /*
|
Chris@87
|
132 * Returns a random unsigned long between 0 and RK_MAX inclusive
|
Chris@87
|
133 */
|
Chris@87
|
134 extern unsigned long rk_random(rk_state *state);
|
Chris@87
|
135
|
Chris@87
|
136 /*
|
Chris@87
|
137 * Returns a random long between 0 and LONG_MAX inclusive
|
Chris@87
|
138 */
|
Chris@87
|
139 extern long rk_long(rk_state *state);
|
Chris@87
|
140
|
Chris@87
|
141 /*
|
Chris@87
|
142 * Returns a random unsigned long between 0 and ULONG_MAX inclusive
|
Chris@87
|
143 */
|
Chris@87
|
144 extern unsigned long rk_ulong(rk_state *state);
|
Chris@87
|
145
|
Chris@87
|
146 /*
|
Chris@87
|
147 * Returns a random unsigned long between 0 and max inclusive.
|
Chris@87
|
148 */
|
Chris@87
|
149 extern unsigned long rk_interval(unsigned long max, rk_state *state);
|
Chris@87
|
150
|
Chris@87
|
151 /*
|
Chris@87
|
152 * Returns a random double between 0.0 and 1.0, 1.0 excluded.
|
Chris@87
|
153 */
|
Chris@87
|
154 extern double rk_double(rk_state *state);
|
Chris@87
|
155
|
Chris@87
|
156 /*
|
Chris@87
|
157 * fill the buffer with size random bytes
|
Chris@87
|
158 */
|
Chris@87
|
159 extern void rk_fill(void *buffer, size_t size, rk_state *state);
|
Chris@87
|
160
|
Chris@87
|
161 /*
|
Chris@87
|
162 * fill the buffer with randombytes from the random device
|
Chris@87
|
163 * Returns RK_ENODEV if the device is unavailable, or RK_NOERR if it is
|
Chris@87
|
164 * On Unix, if strong is defined, RK_DEV_RANDOM is used. If not, RK_DEV_URANDOM
|
Chris@87
|
165 * is used instead. This parameter has no effect on Windows.
|
Chris@87
|
166 * Warning: on most unixes RK_DEV_RANDOM will wait for enough entropy to answer
|
Chris@87
|
167 * which can take a very long time on quiet systems.
|
Chris@87
|
168 */
|
Chris@87
|
169 extern rk_error rk_devfill(void *buffer, size_t size, int strong);
|
Chris@87
|
170
|
Chris@87
|
171 /*
|
Chris@87
|
172 * fill the buffer using rk_devfill if the random device is available and using
|
Chris@87
|
173 * rk_fill if is is not
|
Chris@87
|
174 * parameters have the same meaning as rk_fill and rk_devfill
|
Chris@87
|
175 * Returns RK_ENODEV if the device is unavailable, or RK_NOERR if it is
|
Chris@87
|
176 */
|
Chris@87
|
177 extern rk_error rk_altfill(void *buffer, size_t size, int strong,
|
Chris@87
|
178 rk_state *state);
|
Chris@87
|
179
|
Chris@87
|
180 /*
|
Chris@87
|
181 * return a random gaussian deviate with variance unity and zero mean.
|
Chris@87
|
182 */
|
Chris@87
|
183 extern double rk_gauss(rk_state *state);
|
Chris@87
|
184
|
Chris@87
|
185 #ifdef __cplusplus
|
Chris@87
|
186 }
|
Chris@87
|
187 #endif
|
Chris@87
|
188
|
Chris@87
|
189 #endif /* _RANDOMKIT_ */
|