Mercurial > hg > octave-kai > gnulib-hg
annotate lib/random_r.c @ 16278:0872da28238e
random_r: Use common idioms.
* lib/random_r.c: Include <stdlib.h> first.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 12 Jan 2012 22:55:13 +0100 |
parents | d43b527a2e6c |
children | e542fd46ad6f |
rev | line source |
---|---|
10704 | 1 /* |
16201
8250f2777afc
maint: update all copyright year number ranges
Jim Meyering <meyering@redhat.com>
parents:
14079
diff
changeset
|
2 Copyright (C) 1995, 2005, 2008-2012 Free Software Foundation, Inc. |
10704 | 3 |
12002
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
4 This program is free software: you can redistribute it and/or modify |
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
5 it under the terms of the GNU General Public License as published by |
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
6 the Free Software Foundation; either version 3 of the License, or |
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
7 (at your option) any later version. |
10704 | 8 |
12002
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
9 This program is distributed in the hope that it will be useful, |
10704 | 10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
12002
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
12 GNU General Public License for more details. |
10704 | 13 |
12002
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
14 You should have received a copy of the GNU General Public License |
f295924fa612
Use the standard header with GPL copyright.
Bruno Haible <bruno@clisp.org>
parents:
10704
diff
changeset
|
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
10704 | 16 |
17 /* | |
18 Copyright (C) 1983 Regents of the University of California. | |
19 All rights reserved. | |
20 | |
21 Redistribution and use in source and binary forms, with or without | |
22 modification, are permitted provided that the following conditions | |
23 are met: | |
24 | |
25 1. Redistributions of source code must retain the above copyright | |
26 notice, this list of conditions and the following disclaimer. | |
27 2. Redistributions in binary form must reproduce the above copyright | |
28 notice, this list of conditions and the following disclaimer in the | |
29 documentation and/or other materials provided with the distribution. | |
30 4. Neither the name of the University nor the names of its contributors | |
31 may be used to endorse or promote products derived from this software | |
32 without specific prior written permission. | |
33 | |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
34 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND |
10704 | 35 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
36 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
37 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
38 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
39 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
40 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
41 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
42 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
43 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
44 SUCH DAMAGE.*/ | |
45 | |
46 /* | |
47 * This is derived from the Berkeley source: | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
48 * @(#)random.c 5.5 (Berkeley) 7/6/88 |
10704 | 49 * It was reworked for the GNU C Library by Roland McGrath. |
50 * Rewritten to be reentrant by Ulrich Drepper, 1995 | |
51 */ | |
52 | |
53 #include <config.h> | |
54 | |
12422
f7842310a565
New module 'arg-nonnull'. Declare which arguments expect non-NULL values.
Bruno Haible <bruno@clisp.org>
parents:
12421
diff
changeset
|
55 /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc |
f7842310a565
New module 'arg-nonnull'. Declare which arguments expect non-NULL values.
Bruno Haible <bruno@clisp.org>
parents:
12421
diff
changeset
|
56 optimizes away the buf == NULL, arg_state == NULL, result == NULL tests |
f7842310a565
New module 'arg-nonnull'. Declare which arguments expect non-NULL values.
Bruno Haible <bruno@clisp.org>
parents:
12421
diff
changeset
|
57 below. */ |
f7842310a565
New module 'arg-nonnull'. Declare which arguments expect non-NULL values.
Bruno Haible <bruno@clisp.org>
parents:
12421
diff
changeset
|
58 #define _GL_ARG_NONNULL(params) |
f7842310a565
New module 'arg-nonnull'. Declare which arguments expect non-NULL values.
Bruno Haible <bruno@clisp.org>
parents:
12421
diff
changeset
|
59 |
16278
0872da28238e
random_r: Use common idioms.
Bruno Haible <bruno@clisp.org>
parents:
16276
diff
changeset
|
60 /* Specification. */ |
0872da28238e
random_r: Use common idioms.
Bruno Haible <bruno@clisp.org>
parents:
16276
diff
changeset
|
61 #include <stdlib.h> |
0872da28238e
random_r: Use common idioms.
Bruno Haible <bruno@clisp.org>
parents:
16276
diff
changeset
|
62 |
10704 | 63 #include <errno.h> |
64 #include <limits.h> | |
65 #include <stddef.h> | |
16276
d43b527a2e6c
random_r: Support for MSVC 9.
Bruno Haible <bruno@clisp.org>
parents:
16235
diff
changeset
|
66 #include <stdint.h> |
10704 | 67 |
68 | |
69 /* An improved random number generation package. In addition to the standard | |
70 rand()/srand() like interface, this package also has a special state info | |
71 interface. The initstate() routine is called with a seed, an array of | |
72 bytes, and a count of how many bytes are being passed in; this array is | |
73 then initialized to contain information for random number generation with | |
74 that much state information. Good sizes for the amount of state | |
75 information are 32, 64, 128, and 256 bytes. The state can be switched by | |
76 calling the setstate() function with the same array as was initialized | |
77 with initstate(). By default, the package runs with 128 bytes of state | |
78 information and generates far better random numbers than a linear | |
79 congruential generator. If the amount of state information is less than | |
80 32 bytes, a simple linear congruential R.N.G. is used. Internally, the | |
81 state information is treated as an array of longs; the zeroth element of | |
82 the array is the type of R.N.G. being used (small integer); the remainder | |
83 of the array is the state information for the R.N.G. Thus, 32 bytes of | |
84 state information will give 7 longs worth of state information, which will | |
85 allow a degree seven polynomial. (Note: The zeroth word of state | |
86 information also has some other information stored in it; see setstate | |
87 for details). The random number generation technique is a linear feedback | |
88 shift register approach, employing trinomials (since there are fewer terms | |
89 to sum up that way). In this approach, the least significant bit of all | |
90 the numbers in the state table will act as a linear feedback shift register, | |
91 and will have period 2^deg - 1 (where deg is the degree of the polynomial | |
92 being used, assuming that the polynomial is irreducible and primitive). | |
93 The higher order bits will have longer periods, since their values are | |
94 also influenced by pseudo-random carries out of the lower bits. The | |
95 total period of the generator is approximately deg*(2**deg - 1); thus | |
96 doubling the amount of state information has a vast influence on the | |
97 period of the generator. Note: The deg*(2**deg - 1) is an approximation | |
98 only good for large deg, when the period of the shift register is the | |
99 dominant factor. With deg equal to seven, the period is actually much | |
100 longer than the 7*(2**7 - 1) predicted by this formula. */ | |
101 | |
102 | |
103 | |
104 /* For each of the currently supported random number generators, we have a | |
105 break value on the amount of state information (you need at least this many | |
106 bytes of state info to support this random number generator), a degree for | |
107 the polynomial (actually a trinomial) that the R.N.G. is based on, and | |
108 separation between the two lower order coefficients of the trinomial. */ | |
109 | |
110 /* Linear congruential. */ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
111 #define TYPE_0 0 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
112 #define BREAK_0 8 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
113 #define DEG_0 0 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
114 #define SEP_0 0 |
10704 | 115 |
116 /* x**7 + x**3 + 1. */ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
117 #define TYPE_1 1 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
118 #define BREAK_1 32 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
119 #define DEG_1 7 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
120 #define SEP_1 3 |
10704 | 121 |
122 /* x**15 + x + 1. */ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
123 #define TYPE_2 2 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
124 #define BREAK_2 64 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
125 #define DEG_2 15 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
126 #define SEP_2 1 |
10704 | 127 |
128 /* x**31 + x**3 + 1. */ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
129 #define TYPE_3 3 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
130 #define BREAK_3 128 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
131 #define DEG_3 31 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
132 #define SEP_3 3 |
10704 | 133 |
134 /* x**63 + x + 1. */ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
135 #define TYPE_4 4 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
136 #define BREAK_4 256 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
137 #define DEG_4 63 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
138 #define SEP_4 1 |
10704 | 139 |
140 | |
141 /* Array versions of the above information to make code run faster. | |
142 Relies on fact that TYPE_i == i. */ | |
143 | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
144 #define MAX_TYPES 5 /* Max number of types above. */ |
10704 | 145 |
146 struct random_poly_info | |
147 { | |
148 int seps[MAX_TYPES]; | |
149 int degrees[MAX_TYPES]; | |
150 }; | |
151 | |
152 static const struct random_poly_info random_poly_info = | |
153 { | |
154 { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }, | |
155 { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 } | |
156 }; | |
157 | |
158 #ifndef _LIBC | |
159 # define weak_alias(local, symbol) | |
160 # define __set_errno(e) errno = (e) | |
161 # define __srandom_r srandom_r | |
162 # define __initstate_r initstate_r | |
163 # define __setstate_r setstate_r | |
164 # define __random_r random_r | |
165 #endif | |
166 | |
167 | |
168 | |
169 /* Initialize the random number generator based on the given seed. If the | |
170 type is the trivial no-state-information type, just remember the seed. | |
171 Otherwise, initializes state[] based on the given "seed" via a linear | |
172 congruential generator. Then, the pointers are set to known locations | |
173 that are exactly rand_sep places apart. Lastly, it cycles the state | |
174 information a given number of times to get rid of any initial dependencies | |
175 introduced by the L.C.R.N.G. Note that the initialization of randtbl[] | |
176 for default usage relies on values produced by this routine. */ | |
177 int | |
178 __srandom_r (unsigned int seed, struct random_data *buf) | |
179 { | |
180 int type; | |
181 int32_t *state; | |
182 long int i; | |
183 long int word; | |
184 int32_t *dst; | |
185 int kc; | |
186 | |
187 if (buf == NULL) | |
188 goto fail; | |
189 type = buf->rand_type; | |
190 if ((unsigned int) type >= MAX_TYPES) | |
191 goto fail; | |
192 | |
193 state = buf->state; | |
194 /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ | |
195 if (seed == 0) | |
196 seed = 1; | |
197 state[0] = seed; | |
198 if (type == TYPE_0) | |
199 goto done; | |
200 | |
201 dst = state; | |
202 word = seed; | |
203 kc = buf->rand_deg; | |
204 for (i = 1; i < kc; ++i) | |
205 { | |
206 /* This does: | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
207 state[i] = (16807 * state[i - 1]) % 2147483647; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
208 but avoids overflowing 31 bits. */ |
10704 | 209 long int hi = word / 127773; |
210 long int lo = word % 127773; | |
211 word = 16807 * lo - 2836 * hi; | |
212 if (word < 0) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
213 word += 2147483647; |
10704 | 214 *++dst = word; |
215 } | |
216 | |
217 buf->fptr = &state[buf->rand_sep]; | |
218 buf->rptr = &state[0]; | |
219 kc *= 10; | |
220 while (--kc >= 0) | |
221 { | |
222 int32_t discard; | |
223 (void) __random_r (buf, &discard); | |
224 } | |
225 | |
226 done: | |
227 return 0; | |
228 | |
229 fail: | |
230 return -1; | |
231 } | |
232 | |
233 weak_alias (__srandom_r, srandom_r) | |
234 | |
235 /* Initialize the state information in the given array of N bytes for | |
236 future random number generation. Based on the number of bytes we | |
237 are given, and the break values for the different R.N.G.'s, we choose | |
238 the best (largest) one we can and set things up for it. srandom is | |
239 then called to initialize the state information. Note that on return | |
240 from srandom, we set state[-1] to be the type multiplexed with the current | |
241 value of the rear pointer; this is so successive calls to initstate won't | |
242 lose this information and will be able to restart with setstate. | |
243 Note: The first thing we do is save the current state, if any, just like | |
244 setstate so that it doesn't matter when initstate is called. | |
245 Returns a pointer to the old state. */ | |
246 int | |
247 __initstate_r (unsigned int seed, char *arg_state, size_t n, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
248 struct random_data *buf) |
10704 | 249 { |
250 int32_t *old_state; | |
251 int32_t *state; | |
252 int type; | |
253 int degree; | |
254 int separation; | |
255 | |
256 if (buf == NULL) | |
257 goto fail; | |
258 | |
259 old_state = buf->state; | |
260 if (old_state != NULL) | |
261 { | |
262 int old_type = buf->rand_type; | |
263 if (old_type == TYPE_0) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
264 old_state[-1] = TYPE_0; |
10704 | 265 else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
266 old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; |
10704 | 267 } |
268 | |
269 if (n >= BREAK_3) | |
270 type = n < BREAK_4 ? TYPE_3 : TYPE_4; | |
271 else if (n < BREAK_1) | |
272 { | |
273 if (n < BREAK_0) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
274 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
275 __set_errno (EINVAL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
276 goto fail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
277 } |
10704 | 278 type = TYPE_0; |
279 } | |
280 else | |
281 type = n < BREAK_2 ? TYPE_1 : TYPE_2; | |
282 | |
283 degree = random_poly_info.degrees[type]; | |
284 separation = random_poly_info.seps[type]; | |
285 | |
286 buf->rand_type = type; | |
287 buf->rand_sep = separation; | |
288 buf->rand_deg = degree; | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
289 state = &((int32_t *) arg_state)[1]; /* First location. */ |
10704 | 290 /* Must set END_PTR before srandom. */ |
291 buf->end_ptr = &state[degree]; | |
292 | |
293 buf->state = state; | |
294 | |
295 __srandom_r (seed, buf); | |
296 | |
297 state[-1] = TYPE_0; | |
298 if (type != TYPE_0) | |
299 state[-1] = (buf->rptr - state) * MAX_TYPES + type; | |
300 | |
301 return 0; | |
302 | |
303 fail: | |
304 __set_errno (EINVAL); | |
305 return -1; | |
306 } | |
307 | |
308 weak_alias (__initstate_r, initstate_r) | |
309 | |
310 /* Restore the state from the given state array. | |
311 Note: It is important that we also remember the locations of the pointers | |
312 in the current state information, and restore the locations of the pointers | |
313 from the old state information. This is done by multiplexing the pointer | |
314 location into the zeroth word of the state information. Note that due | |
315 to the order in which things are done, it is OK to call setstate with the | |
316 same state as the current state | |
317 Returns a pointer to the old state information. */ | |
318 int | |
319 __setstate_r (char *arg_state, struct random_data *buf) | |
320 { | |
321 int32_t *new_state = 1 + (int32_t *) arg_state; | |
322 int type; | |
323 int old_type; | |
324 int32_t *old_state; | |
325 int degree; | |
326 int separation; | |
327 | |
328 if (arg_state == NULL || buf == NULL) | |
329 goto fail; | |
330 | |
331 old_type = buf->rand_type; | |
332 old_state = buf->state; | |
333 if (old_type == TYPE_0) | |
334 old_state[-1] = TYPE_0; | |
335 else | |
336 old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; | |
337 | |
338 type = new_state[-1] % MAX_TYPES; | |
339 if (type < TYPE_0 || type > TYPE_4) | |
340 goto fail; | |
341 | |
342 buf->rand_deg = degree = random_poly_info.degrees[type]; | |
343 buf->rand_sep = separation = random_poly_info.seps[type]; | |
344 buf->rand_type = type; | |
345 | |
346 if (type != TYPE_0) | |
347 { | |
348 int rear = new_state[-1] / MAX_TYPES; | |
349 buf->rptr = &new_state[rear]; | |
350 buf->fptr = &new_state[(rear + separation) % degree]; | |
351 } | |
352 buf->state = new_state; | |
353 /* Set end_ptr too. */ | |
354 buf->end_ptr = &new_state[degree]; | |
355 | |
356 return 0; | |
357 | |
358 fail: | |
359 __set_errno (EINVAL); | |
360 return -1; | |
361 } | |
362 | |
363 weak_alias (__setstate_r, setstate_r) | |
364 | |
365 /* If we are using the trivial TYPE_0 R.N.G., just do the old linear | |
366 congruential bit. Otherwise, we do our fancy trinomial stuff, which is the | |
367 same in all the other cases due to all the global variables that have been | |
368 set up. The basic operation is to add the number at the rear pointer into | |
369 the one at the front pointer. Then both pointers are advanced to the next | |
370 location cyclically in the table. The value returned is the sum generated, | |
371 reduced to 31 bits by throwing away the "least random" low bit. | |
372 Note: The code takes advantage of the fact that both the front and | |
373 rear pointers can't wrap on the same call by not testing the rear | |
374 pointer if the front one has wrapped. Returns a 31-bit random number. */ | |
375 | |
376 int | |
377 __random_r (struct random_data *buf, int32_t *result) | |
378 { | |
379 int32_t *state; | |
380 | |
381 if (buf == NULL || result == NULL) | |
382 goto fail; | |
383 | |
384 state = buf->state; | |
385 | |
386 if (buf->rand_type == TYPE_0) | |
387 { | |
388 int32_t val = state[0]; | |
389 val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; | |
390 state[0] = val; | |
391 *result = val; | |
392 } | |
393 else | |
394 { | |
395 int32_t *fptr = buf->fptr; | |
396 int32_t *rptr = buf->rptr; | |
397 int32_t *end_ptr = buf->end_ptr; | |
398 int32_t val; | |
399 | |
400 val = *fptr += *rptr; | |
401 /* Chucking least random bit. */ | |
402 *result = (val >> 1) & 0x7fffffff; | |
403 ++fptr; | |
404 if (fptr >= end_ptr) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
405 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
406 fptr = state; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
407 ++rptr; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
408 } |
10704 | 409 else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
410 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
411 ++rptr; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
412 if (rptr >= end_ptr) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
413 rptr = state; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12002
diff
changeset
|
414 } |
10704 | 415 buf->fptr = fptr; |
416 buf->rptr = rptr; | |
417 } | |
418 return 0; | |
419 | |
420 fail: | |
421 __set_errno (EINVAL); | |
422 return -1; | |
423 } | |
424 | |
425 weak_alias (__random_r, random_r) |