18a16b7a1SPedro F. Giffuni /*-
28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni *
458f0484fSRodney W. Grimes * Copyright (c) 1983, 1993
558f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved.
658f0484fSRodney W. Grimes *
758f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without
858f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions
958f0484fSRodney W. Grimes * are met:
1058f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
1158f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer.
1258f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
1358f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
1458f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution.
15580b4d18SEd Maste * 3. Neither the name of the University nor the names of its contributors
1658f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software
1758f0484fSRodney W. Grimes * without specific prior written permission.
1858f0484fSRodney W. Grimes *
1958f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2058f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2158f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2258f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2358f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2458f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2558f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2658f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2758f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2858f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2958f0484fSRodney W. Grimes * SUCH DAMAGE.
3058f0484fSRodney W. Grimes */
3158f0484fSRodney W. Grimes
3258f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint)
334381233dSPeter Wemm static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95";
3458f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */
35d201fe46SDaniel Eischen #include "namespace.h"
3612a68650SXin LI #include <sys/param.h>
3712a68650SXin LI #include <sys/sysctl.h>
38510b0183SConrad Meyer #include <errno.h>
39307649e2SDavid Schultz #include <stdint.h>
4058f0484fSRodney W. Grimes #include <stdlib.h>
41d201fe46SDaniel Eischen #include "un-namespace.h"
4258f0484fSRodney W. Grimes
43510b0183SConrad Meyer #include "random.h"
44510b0183SConrad Meyer
4558f0484fSRodney W. Grimes /*
4658f0484fSRodney W. Grimes * random.c:
4758f0484fSRodney W. Grimes *
4858f0484fSRodney W. Grimes * An improved random number generation package. In addition to the standard
4958f0484fSRodney W. Grimes * rand()/srand() like interface, this package also has a special state info
5058f0484fSRodney W. Grimes * interface. The initstate() routine is called with a seed, an array of
5158f0484fSRodney W. Grimes * bytes, and a count of how many bytes are being passed in; this array is
5258f0484fSRodney W. Grimes * then initialized to contain information for random number generation with
5358f0484fSRodney W. Grimes * that much state information. Good sizes for the amount of state
5458f0484fSRodney W. Grimes * information are 32, 64, 128, and 256 bytes. The state can be switched by
5558f0484fSRodney W. Grimes * calling the setstate() routine with the same array as was initiallized
5658f0484fSRodney W. Grimes * with initstate(). By default, the package runs with 128 bytes of state
5758f0484fSRodney W. Grimes * information and generates far better random numbers than a linear
5858f0484fSRodney W. Grimes * congruential generator. If the amount of state information is less than
5958f0484fSRodney W. Grimes * 32 bytes, a simple linear congruential R.N.G. is used.
6058f0484fSRodney W. Grimes *
61307649e2SDavid Schultz * Internally, the state information is treated as an array of uint32_t's; the
6258f0484fSRodney W. Grimes * zeroeth element of the array is the type of R.N.G. being used (small
6358f0484fSRodney W. Grimes * integer); the remainder of the array is the state information for the
64307649e2SDavid Schultz * R.N.G. Thus, 32 bytes of state information will give 7 ints worth of
6558f0484fSRodney W. Grimes * state information, which will allow a degree seven polynomial. (Note:
6658f0484fSRodney W. Grimes * the zeroeth word of state information also has some other information
6758f0484fSRodney W. Grimes * stored in it -- see setstate() for details).
6858f0484fSRodney W. Grimes *
6958f0484fSRodney W. Grimes * The random number generation technique is a linear feedback shift register
7058f0484fSRodney W. Grimes * approach, employing trinomials (since there are fewer terms to sum up that
7158f0484fSRodney W. Grimes * way). In this approach, the least significant bit of all the numbers in
7258f0484fSRodney W. Grimes * the state table will act as a linear feedback shift register, and will
7358f0484fSRodney W. Grimes * have period 2^deg - 1 (where deg is the degree of the polynomial being
7458f0484fSRodney W. Grimes * used, assuming that the polynomial is irreducible and primitive). The
7558f0484fSRodney W. Grimes * higher order bits will have longer periods, since their values are also
7658f0484fSRodney W. Grimes * influenced by pseudo-random carries out of the lower bits. The total
7758f0484fSRodney W. Grimes * period of the generator is approximately deg*(2**deg - 1); thus doubling
7858f0484fSRodney W. Grimes * the amount of state information has a vast influence on the period of the
7958f0484fSRodney W. Grimes * generator. Note: the deg*(2**deg - 1) is an approximation only good for
808fb3f3f6SDavid E. O'Brien * large deg, when the period of the shift is the dominant factor.
8158f0484fSRodney W. Grimes * With deg equal to seven, the period is actually much longer than the
8258f0484fSRodney W. Grimes * 7*(2**7 - 1) predicted by this formula.
834381233dSPeter Wemm *
844381233dSPeter Wemm * Modified 28 December 1994 by Jacob S. Rosenberg.
854381233dSPeter Wemm * The following changes have been made:
864381233dSPeter Wemm * All references to the type u_int have been changed to unsigned long.
874381233dSPeter Wemm * All references to type int have been changed to type long. Other
884381233dSPeter Wemm * cleanups have been made as well. A warning for both initstate and
894381233dSPeter Wemm * setstate has been inserted to the effect that on Sparc platforms
904381233dSPeter Wemm * the 'arg_state' variable must be forced to begin on word boundaries.
914381233dSPeter Wemm * This can be easily done by casting a long integer array to char *.
924381233dSPeter Wemm * The overall logic has been left STRICTLY alone. This software was
934381233dSPeter Wemm * tested on both a VAX and Sun SpacsStation with exactly the same
944381233dSPeter Wemm * results. The new version and the original give IDENTICAL results.
954381233dSPeter Wemm * The new version is somewhat faster than the original. As the
964381233dSPeter Wemm * documentation says: "By default, the package runs with 128 bytes of
974381233dSPeter Wemm * state information and generates far better random numbers than a linear
984381233dSPeter Wemm * congruential generator. If the amount of state information is less than
994381233dSPeter Wemm * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of
1004381233dSPeter Wemm * 128 bytes, this new version runs about 19 percent faster and for a 16
1014381233dSPeter Wemm * byte buffer it is about 5 percent faster.
10258f0484fSRodney W. Grimes */
10358f0484fSRodney W. Grimes
10440220ddeSAndrey A. Chernov #define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
105ddd972a9SAndrey A. Chernov
106307649e2SDavid Schultz static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
107307649e2SDavid Schultz static const int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
108*672e1225SConrad Meyer static const int breaks[MAX_TYPES] = {
109*672e1225SConrad Meyer BREAK_0, BREAK_1, BREAK_2, BREAK_3, BREAK_4
110*672e1225SConrad Meyer };
11158f0484fSRodney W. Grimes
11258f0484fSRodney W. Grimes /*
11358f0484fSRodney W. Grimes * Initially, everything is set up as if from:
11458f0484fSRodney W. Grimes *
11540f8b70dSAndrey A. Chernov * initstate(1, randtbl, 128);
11658f0484fSRodney W. Grimes *
11758f0484fSRodney W. Grimes * Note that this initialization takes advantage of the fact that srandom()
11858f0484fSRodney W. Grimes * advances the front and rear pointers 10*rand_deg times, and hence the
11958f0484fSRodney W. Grimes * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
12058f0484fSRodney W. Grimes * element of the state information, which contains info about the current
12158f0484fSRodney W. Grimes * position of the rear pointer is just
12258f0484fSRodney W. Grimes *
12358f0484fSRodney W. Grimes * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
12458f0484fSRodney W. Grimes */
125510b0183SConrad Meyer static struct __random_state implicit = {
1267382fafeSConrad Meyer .rst_randtbl = {
12758f0484fSRodney W. Grimes TYPE_3,
128e44ffdb2SAndrey A. Chernov 0x2cf41758, 0x27bb3711, 0x4916d4d1, 0x7b02f59f, 0x9b8e28eb, 0xc0e80269,
129e44ffdb2SAndrey A. Chernov 0x696f5c16, 0x878f1ff5, 0x52d9c07f, 0x916a06cd, 0xb50b3a20, 0x2776970a,
130e44ffdb2SAndrey A. Chernov 0xee4eb2a6, 0xe94640ec, 0xb1d65612, 0x9d1ed968, 0x1043f6b7, 0xa3432a76,
131e44ffdb2SAndrey A. Chernov 0x17eacbb9, 0x3c09e2eb, 0x4f8c2b3, 0x708a1f57, 0xee341814, 0x95d0e4d2,
132e44ffdb2SAndrey A. Chernov 0xb06f216c, 0x8bd2e72e, 0x8f7c38d7, 0xcfc6a8fc, 0x2a59495, 0xa20d2a69,
133e44ffdb2SAndrey A. Chernov 0xe29d12d1
1347382fafeSConrad Meyer },
13558f0484fSRodney W. Grimes
13658f0484fSRodney W. Grimes /*
13758f0484fSRodney W. Grimes * fptr and rptr are two pointers into the state info, a front and a rear
13858f0484fSRodney W. Grimes * pointer. These two pointers are always rand_sep places aparts, as they
13958f0484fSRodney W. Grimes * cycle cyclically through the state information. (Yes, this does mean we
14058f0484fSRodney W. Grimes * could get away with just one pointer, but the code for random() is more
14158f0484fSRodney W. Grimes * efficient this way). The pointers are left positioned as they would be
14258f0484fSRodney W. Grimes * from the call
14358f0484fSRodney W. Grimes *
14458f0484fSRodney W. Grimes * initstate(1, randtbl, 128);
14558f0484fSRodney W. Grimes *
14658f0484fSRodney W. Grimes * (The position of the rear pointer, rptr, is really 0 (as explained above
14758f0484fSRodney W. Grimes * in the initialization of randtbl) because the state table pointer is set
14858f0484fSRodney W. Grimes * to point to randtbl[1] (as explained below).
14958f0484fSRodney W. Grimes */
1507382fafeSConrad Meyer .rst_fptr = &implicit.rst_randtbl[SEP_3 + 1],
1517382fafeSConrad Meyer .rst_rptr = &implicit.rst_randtbl[1],
15258f0484fSRodney W. Grimes
15358f0484fSRodney W. Grimes /*
15458f0484fSRodney W. Grimes * The following things are the pointer to the state information table, the
15558f0484fSRodney W. Grimes * type of the current generator, the degree of the current polynomial being
15658f0484fSRodney W. Grimes * used, and the separation between the two pointers. Note that for efficiency
15758f0484fSRodney W. Grimes * of random(), we remember the first location of the state information, not
15858f0484fSRodney W. Grimes * the zeroeth. Hence it is valid to access state[-1], which is used to
15958f0484fSRodney W. Grimes * store the type of the R.N.G. Also, we remember the last location, since
16058f0484fSRodney W. Grimes * this is more efficient than indexing every time to find the address of
16158f0484fSRodney W. Grimes * the last element to see if the front and rear pointers have wrapped.
16258f0484fSRodney W. Grimes */
1637382fafeSConrad Meyer .rst_state = &implicit.rst_randtbl[1],
1647382fafeSConrad Meyer .rst_type = TYPE_3,
1657382fafeSConrad Meyer .rst_deg = DEG_3,
1667382fafeSConrad Meyer .rst_sep = SEP_3,
1677382fafeSConrad Meyer .rst_end_ptr = &implicit.rst_randtbl[DEG_3 + 1],
1687382fafeSConrad Meyer };
16958f0484fSRodney W. Grimes
1707382fafeSConrad Meyer /*
1717382fafeSConrad Meyer * This is the same low quality PRNG used in rand(3) in FreeBSD 12 and prior.
1727382fafeSConrad Meyer * It may be sufficient for distributing bits and expanding a small seed
1737382fafeSConrad Meyer * integer into a larger state.
1747382fafeSConrad Meyer */
175d7555525SDag-Erling Smørgrav static inline uint32_t
parkmiller32(uint32_t ctx)1767382fafeSConrad Meyer parkmiller32(uint32_t ctx)
17740f8b70dSAndrey A. Chernov {
17840f8b70dSAndrey A. Chernov /*
17940f8b70dSAndrey A. Chernov * Compute x = (7^5 * x) mod (2^31 - 1)
18040f8b70dSAndrey A. Chernov * wihout overflowing 31 bits:
18140f8b70dSAndrey A. Chernov * (2^31 - 1) = 127773 * (7^5) + 2836
18240f8b70dSAndrey A. Chernov * From "Random number generators: good ones are hard to find",
18340f8b70dSAndrey A. Chernov * Park and Miller, Communications of the ACM, vol. 31, no. 10,
18440f8b70dSAndrey A. Chernov * October 1988, p. 1195.
18540f8b70dSAndrey A. Chernov */
186e44ffdb2SAndrey A. Chernov int32_t hi, lo, x;
18740f8b70dSAndrey A. Chernov
188e44ffdb2SAndrey A. Chernov /* Transform to [1, 0x7ffffffe] range. */
189e44ffdb2SAndrey A. Chernov x = (ctx % 0x7ffffffe) + 1;
19040f8b70dSAndrey A. Chernov hi = x / 127773;
19140f8b70dSAndrey A. Chernov lo = x % 127773;
19240f8b70dSAndrey A. Chernov x = 16807 * lo - 2836 * hi;
1932f5ef51dSAndrey A. Chernov if (x < 0)
19440f8b70dSAndrey A. Chernov x += 0x7fffffff;
195e44ffdb2SAndrey A. Chernov /* Transform to [0, 0x7ffffffd] range. */
196e44ffdb2SAndrey A. Chernov return (x - 1);
19740f8b70dSAndrey A. Chernov }
19840f8b70dSAndrey A. Chernov
19958f0484fSRodney W. Grimes /*
20058f0484fSRodney W. Grimes * srandom:
20158f0484fSRodney W. Grimes *
20258f0484fSRodney W. Grimes * Initialize the random number generator based on the given seed. If the
20358f0484fSRodney W. Grimes * type is the trivial no-state-information type, just remember the seed.
20458f0484fSRodney W. Grimes * Otherwise, initializes state[] based on the given "seed" via a linear
20558f0484fSRodney W. Grimes * congruential generator. Then, the pointers are set to known locations
20658f0484fSRodney W. Grimes * that are exactly rand_sep places apart. Lastly, it cycles the state
20758f0484fSRodney W. Grimes * information a given number of times to get rid of any initial dependencies
20858f0484fSRodney W. Grimes * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
20958f0484fSRodney W. Grimes * for default usage relies on values produced by this routine.
21058f0484fSRodney W. Grimes */
21158f0484fSRodney W. Grimes void
srandom_r(struct __random_state * estate,unsigned x)212510b0183SConrad Meyer srandom_r(struct __random_state *estate, unsigned x)
21358f0484fSRodney W. Grimes {
214307649e2SDavid Schultz int i, lim;
21558f0484fSRodney W. Grimes
216510b0183SConrad Meyer estate->rst_state[0] = (uint32_t)x;
217510b0183SConrad Meyer if (estate->rst_type == TYPE_0)
218ddd972a9SAndrey A. Chernov lim = NSHUFF;
21958f0484fSRodney W. Grimes else {
220510b0183SConrad Meyer for (i = 1; i < estate->rst_deg; i++)
221510b0183SConrad Meyer estate->rst_state[i] =
222510b0183SConrad Meyer parkmiller32(estate->rst_state[i - 1]);
223510b0183SConrad Meyer estate->rst_fptr = &estate->rst_state[estate->rst_sep];
224510b0183SConrad Meyer estate->rst_rptr = &estate->rst_state[0];
225510b0183SConrad Meyer lim = 10 * estate->rst_deg;
22658f0484fSRodney W. Grimes }
227ddd972a9SAndrey A. Chernov for (i = 0; i < lim; i++)
228510b0183SConrad Meyer (void)random_r(estate);
229510b0183SConrad Meyer }
230510b0183SConrad Meyer
231510b0183SConrad Meyer void
srandom(unsigned x)232510b0183SConrad Meyer srandom(unsigned x)
233510b0183SConrad Meyer {
234510b0183SConrad Meyer srandom_r(&implicit, x);
23558f0484fSRodney W. Grimes }
23658f0484fSRodney W. Grimes
23758f0484fSRodney W. Grimes /*
238301cf5d3SAndrey A. Chernov * srandomdev:
239301cf5d3SAndrey A. Chernov *
240301cf5d3SAndrey A. Chernov * Many programs choose the seed value in a totally predictable manner.
24112a68650SXin LI * This often causes problems. We seed the generator using pseudo-random
24212a68650SXin LI * data from the kernel.
24312a68650SXin LI *
24412a68650SXin LI * Note that this particular seeding procedure can generate states
24512a68650SXin LI * which are impossible to reproduce by calling srandom() with any
24612a68650SXin LI * value, since the succeeding terms in the state buffer are no longer
24712a68650SXin LI * derived from the LC algorithm applied to a fixed seed.
248301cf5d3SAndrey A. Chernov */
24996c31b26SAndrey A. Chernov void
srandomdev_r(struct __random_state * estate)250510b0183SConrad Meyer srandomdev_r(struct __random_state *estate)
251301cf5d3SAndrey A. Chernov {
25212a68650SXin LI int mib[2];
2537e81ad12SEd Maste size_t expected, len;
254301cf5d3SAndrey A. Chernov
255510b0183SConrad Meyer if (estate->rst_type == TYPE_0)
256510b0183SConrad Meyer len = sizeof(estate->rst_state[0]);
257301cf5d3SAndrey A. Chernov else
258510b0183SConrad Meyer len = estate->rst_deg * sizeof(estate->rst_state[0]);
2597382fafeSConrad Meyer expected = len;
260301cf5d3SAndrey A. Chernov
26112a68650SXin LI mib[0] = CTL_KERN;
26212a68650SXin LI mib[1] = KERN_ARND;
263510b0183SConrad Meyer if (sysctl(mib, 2, estate->rst_state, &len, NULL, 0) == -1 ||
2647382fafeSConrad Meyer len != expected) {
26549a6e1baSEd Maste /*
26649a6e1baSEd Maste * The sysctl cannot fail. If it does fail on some FreeBSD
26749a6e1baSEd Maste * derivative or after some future change, just abort so that
26849a6e1baSEd Maste * the problem will be found and fixed. abort is not normally
26949a6e1baSEd Maste * suitable for a library but makes sense here.
27049a6e1baSEd Maste */
2717e81ad12SEd Maste abort();
27249a6e1baSEd Maste }
273301cf5d3SAndrey A. Chernov
274510b0183SConrad Meyer if (estate->rst_type != TYPE_0) {
275510b0183SConrad Meyer estate->rst_fptr = &estate->rst_state[estate->rst_sep];
276510b0183SConrad Meyer estate->rst_rptr = &estate->rst_state[0];
277301cf5d3SAndrey A. Chernov }
278301cf5d3SAndrey A. Chernov }
279301cf5d3SAndrey A. Chernov
280510b0183SConrad Meyer void
srandomdev(void)281510b0183SConrad Meyer srandomdev(void)
282510b0183SConrad Meyer {
283510b0183SConrad Meyer srandomdev_r(&implicit);
284510b0183SConrad Meyer }
285510b0183SConrad Meyer
286301cf5d3SAndrey A. Chernov /*
287510b0183SConrad Meyer * initstate_r:
28858f0484fSRodney W. Grimes *
28958f0484fSRodney W. Grimes * Initialize the state information in the given array of n bytes for future
29058f0484fSRodney W. Grimes * random number generation. Based on the number of bytes we are given, and
29158f0484fSRodney W. Grimes * the break values for the different R.N.G.'s, we choose the best (largest)
29258f0484fSRodney W. Grimes * one we can and set things up for it. srandom() is then called to
29358f0484fSRodney W. Grimes * initialize the state information.
29458f0484fSRodney W. Grimes *
295510b0183SConrad Meyer * Returns zero on success, or an error number on failure.
296510b0183SConrad Meyer *
297510b0183SConrad Meyer * Note: There is no need for a setstate_r(); just use a new context.
298510b0183SConrad Meyer */
299510b0183SConrad Meyer int
initstate_r(struct __random_state * estate,unsigned seed,uint32_t * arg_state,size_t sz)300510b0183SConrad Meyer initstate_r(struct __random_state *estate, unsigned seed, uint32_t *arg_state,
301510b0183SConrad Meyer size_t sz)
302510b0183SConrad Meyer {
303510b0183SConrad Meyer if (sz < BREAK_0)
304510b0183SConrad Meyer return (EINVAL);
305510b0183SConrad Meyer
306510b0183SConrad Meyer if (sz < BREAK_1) {
307510b0183SConrad Meyer estate->rst_type = TYPE_0;
308510b0183SConrad Meyer estate->rst_deg = DEG_0;
309510b0183SConrad Meyer estate->rst_sep = SEP_0;
310510b0183SConrad Meyer } else if (sz < BREAK_2) {
311510b0183SConrad Meyer estate->rst_type = TYPE_1;
312510b0183SConrad Meyer estate->rst_deg = DEG_1;
313510b0183SConrad Meyer estate->rst_sep = SEP_1;
314510b0183SConrad Meyer } else if (sz < BREAK_3) {
315510b0183SConrad Meyer estate->rst_type = TYPE_2;
316510b0183SConrad Meyer estate->rst_deg = DEG_2;
317510b0183SConrad Meyer estate->rst_sep = SEP_2;
318510b0183SConrad Meyer } else if (sz < BREAK_4) {
319510b0183SConrad Meyer estate->rst_type = TYPE_3;
320510b0183SConrad Meyer estate->rst_deg = DEG_3;
321510b0183SConrad Meyer estate->rst_sep = SEP_3;
322510b0183SConrad Meyer } else {
323510b0183SConrad Meyer estate->rst_type = TYPE_4;
324510b0183SConrad Meyer estate->rst_deg = DEG_4;
325510b0183SConrad Meyer estate->rst_sep = SEP_4;
326510b0183SConrad Meyer }
327510b0183SConrad Meyer estate->rst_state = arg_state + 1;
328510b0183SConrad Meyer estate->rst_end_ptr = &estate->rst_state[estate->rst_deg];
329510b0183SConrad Meyer srandom_r(estate, seed);
330510b0183SConrad Meyer return (0);
331510b0183SConrad Meyer }
332510b0183SConrad Meyer
333510b0183SConrad Meyer /*
334510b0183SConrad Meyer * initstate:
33558f0484fSRodney W. Grimes *
33658f0484fSRodney W. Grimes * Note: the first thing we do is save the current state, if any, just like
33758f0484fSRodney W. Grimes * setstate() so that it doesn't matter when initstate is called.
33858f0484fSRodney W. Grimes *
339510b0183SConrad Meyer * Note that on return from initstate_r(), we set state[-1] to be the type
340510b0183SConrad Meyer * multiplexed with the current value of the rear pointer; this is so
341510b0183SConrad Meyer * successive calls to initstate() won't lose this information and will be able
342510b0183SConrad Meyer * to restart with setstate().
343510b0183SConrad Meyer *
34458f0484fSRodney W. Grimes * Returns a pointer to the old state.
3454381233dSPeter Wemm *
346510b0183SConrad Meyer * Despite the misleading "char *" type, arg_state must alias an array of
347510b0183SConrad Meyer * 32-bit unsigned integer values. Naturally, such an array is 32-bit aligned.
348510b0183SConrad Meyer * Usually objects are naturally aligned to at least 32-bits on all platforms,
349510b0183SConrad Meyer * but if you treat the provided 'state' as char* you may inadvertently
350510b0183SConrad Meyer * misalign it. Don't do that.
35158f0484fSRodney W. Grimes */
35258f0484fSRodney W. Grimes char *
initstate(unsigned int seed,char * arg_state,size_t n)3538de6c267SEd Schouten initstate(unsigned int seed, char *arg_state, size_t n)
35458f0484fSRodney W. Grimes {
3557382fafeSConrad Meyer char *ostate = (char *)(&implicit.rst_state[-1]);
356307649e2SDavid Schultz uint32_t *int_arg_state = (uint32_t *)arg_state;
357510b0183SConrad Meyer int error;
35858f0484fSRodney W. Grimes
359510b0183SConrad Meyer /*
360510b0183SConrad Meyer * Persist rptr offset and rst_type in the first word of the prior
361510b0183SConrad Meyer * state we are replacing.
362510b0183SConrad Meyer */
3637382fafeSConrad Meyer if (implicit.rst_type == TYPE_0)
3647382fafeSConrad Meyer implicit.rst_state[-1] = implicit.rst_type;
36558f0484fSRodney W. Grimes else
3667382fafeSConrad Meyer implicit.rst_state[-1] = MAX_TYPES *
3677382fafeSConrad Meyer (implicit.rst_rptr - implicit.rst_state) +
3687382fafeSConrad Meyer implicit.rst_type;
369510b0183SConrad Meyer
370510b0183SConrad Meyer error = initstate_r(&implicit, seed, int_arg_state, n);
371510b0183SConrad Meyer if (error != 0)
372510b0183SConrad Meyer return (NULL);
373510b0183SConrad Meyer
374510b0183SConrad Meyer /*
375510b0183SConrad Meyer * Persist rptr offset and rst_type of the new state in its first word.
376510b0183SConrad Meyer */
3777382fafeSConrad Meyer if (implicit.rst_type == TYPE_0)
3787382fafeSConrad Meyer int_arg_state[0] = implicit.rst_type;
37958f0484fSRodney W. Grimes else
3807382fafeSConrad Meyer int_arg_state[0] = MAX_TYPES *
3817382fafeSConrad Meyer (implicit.rst_rptr - implicit.rst_state) +
3827382fafeSConrad Meyer implicit.rst_type;
383510b0183SConrad Meyer
38458f0484fSRodney W. Grimes return (ostate);
38558f0484fSRodney W. Grimes }
38658f0484fSRodney W. Grimes
38758f0484fSRodney W. Grimes /*
38858f0484fSRodney W. Grimes * setstate:
38958f0484fSRodney W. Grimes *
39058f0484fSRodney W. Grimes * Restore the state from the given state array.
39158f0484fSRodney W. Grimes *
39258f0484fSRodney W. Grimes * Note: it is important that we also remember the locations of the pointers
39358f0484fSRodney W. Grimes * in the current state information, and restore the locations of the pointers
39458f0484fSRodney W. Grimes * from the old state information. This is done by multiplexing the pointer
39558f0484fSRodney W. Grimes * location into the zeroeth word of the state information.
39658f0484fSRodney W. Grimes *
39758f0484fSRodney W. Grimes * Note that due to the order in which things are done, it is OK to call
39858f0484fSRodney W. Grimes * setstate() with the same state as the current state.
39958f0484fSRodney W. Grimes *
40058f0484fSRodney W. Grimes * Returns a pointer to the old state information.
4014381233dSPeter Wemm *
402307649e2SDavid Schultz * Note: The Sparc platform requires that arg_state begin on an int
4034381233dSPeter Wemm * word boundary; otherwise a bus error will occur. Even so, lint will
4044381233dSPeter Wemm * complain about mis-alignment, but you should disregard these messages.
40558f0484fSRodney W. Grimes */
40658f0484fSRodney W. Grimes char *
setstate(char * arg_state)407d7555525SDag-Erling Smørgrav setstate(char *arg_state)
40858f0484fSRodney W. Grimes {
409307649e2SDavid Schultz uint32_t *new_state = (uint32_t *)arg_state;
410307649e2SDavid Schultz uint32_t type = new_state[0] % MAX_TYPES;
411307649e2SDavid Schultz uint32_t rear = new_state[0] / MAX_TYPES;
4127382fafeSConrad Meyer char *ostate = (char *)(&implicit.rst_state[-1]);
41358f0484fSRodney W. Grimes
414e44ffdb2SAndrey A. Chernov if (type != TYPE_0 && rear >= degrees[type])
415fbd6b95eSAndrey A. Chernov return (NULL);
4167382fafeSConrad Meyer if (implicit.rst_type == TYPE_0)
4177382fafeSConrad Meyer implicit.rst_state[-1] = implicit.rst_type;
418fbd6b95eSAndrey A. Chernov else
4197382fafeSConrad Meyer implicit.rst_state[-1] = MAX_TYPES *
4207382fafeSConrad Meyer (implicit.rst_rptr - implicit.rst_state) +
4217382fafeSConrad Meyer implicit.rst_type;
4227382fafeSConrad Meyer implicit.rst_type = type;
4237382fafeSConrad Meyer implicit.rst_deg = degrees[type];
4247382fafeSConrad Meyer implicit.rst_sep = seps[type];
4257382fafeSConrad Meyer implicit.rst_state = new_state + 1;
4267382fafeSConrad Meyer if (implicit.rst_type != TYPE_0) {
4277382fafeSConrad Meyer implicit.rst_rptr = &implicit.rst_state[rear];
4287382fafeSConrad Meyer implicit.rst_fptr = &implicit.rst_state[
4297382fafeSConrad Meyer (rear + implicit.rst_sep) % implicit.rst_deg];
43058f0484fSRodney W. Grimes }
4317382fafeSConrad Meyer implicit.rst_end_ptr = &implicit.rst_state[implicit.rst_deg];
43258f0484fSRodney W. Grimes return (ostate);
43358f0484fSRodney W. Grimes }
43458f0484fSRodney W. Grimes
43558f0484fSRodney W. Grimes /*
43658f0484fSRodney W. Grimes * random:
43758f0484fSRodney W. Grimes *
43858f0484fSRodney W. Grimes * If we are using the trivial TYPE_0 R.N.G., just do the old linear
43958f0484fSRodney W. Grimes * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
44058f0484fSRodney W. Grimes * the same in all the other cases due to all the global variables that have
44158f0484fSRodney W. Grimes * been set up. The basic operation is to add the number at the rear pointer
44258f0484fSRodney W. Grimes * into the one at the front pointer. Then both pointers are advanced to
44358f0484fSRodney W. Grimes * the next location cyclically in the table. The value returned is the sum
44458f0484fSRodney W. Grimes * generated, reduced to 31 bits by throwing away the "least random" low bit.
44558f0484fSRodney W. Grimes *
44658f0484fSRodney W. Grimes * Note: the code takes advantage of the fact that both the front and
44758f0484fSRodney W. Grimes * rear pointers can't wrap on the same call by not testing the rear
44858f0484fSRodney W. Grimes * pointer if the front one has wrapped.
44958f0484fSRodney W. Grimes *
45058f0484fSRodney W. Grimes * Returns a 31-bit random number.
45158f0484fSRodney W. Grimes */
45258f0484fSRodney W. Grimes long
random_r(struct __random_state * estate)453510b0183SConrad Meyer random_r(struct __random_state *estate)
45458f0484fSRodney W. Grimes {
455307649e2SDavid Schultz uint32_t i;
456307649e2SDavid Schultz uint32_t *f, *r;
45758f0484fSRodney W. Grimes
458510b0183SConrad Meyer if (estate->rst_type == TYPE_0) {
459510b0183SConrad Meyer i = estate->rst_state[0];
4607382fafeSConrad Meyer i = parkmiller32(i);
461510b0183SConrad Meyer estate->rst_state[0] = i;
4624381233dSPeter Wemm } else {
4634381233dSPeter Wemm /*
4644381233dSPeter Wemm * Use local variables rather than static variables for speed.
4654381233dSPeter Wemm */
466510b0183SConrad Meyer f = estate->rst_fptr;
467510b0183SConrad Meyer r = estate->rst_rptr;
4684381233dSPeter Wemm *f += *r;
469b8ac3f20SAndrey A. Chernov i = *f >> 1; /* chucking least random bit */
470510b0183SConrad Meyer if (++f >= estate->rst_end_ptr) {
471510b0183SConrad Meyer f = estate->rst_state;
4724381233dSPeter Wemm ++r;
4734381233dSPeter Wemm }
474510b0183SConrad Meyer else if (++r >= estate->rst_end_ptr) {
475510b0183SConrad Meyer r = estate->rst_state;
4764381233dSPeter Wemm }
4774381233dSPeter Wemm
478510b0183SConrad Meyer estate->rst_fptr = f;
479510b0183SConrad Meyer estate->rst_rptr = r;
48058f0484fSRodney W. Grimes }
481307649e2SDavid Schultz return ((long)i);
48258f0484fSRodney W. Grimes }
483510b0183SConrad Meyer
484510b0183SConrad Meyer long
random(void)485510b0183SConrad Meyer random(void)
486510b0183SConrad Meyer {
487510b0183SConrad Meyer return (random_r(&implicit));
488510b0183SConrad Meyer }
489*672e1225SConrad Meyer
490*672e1225SConrad Meyer struct __random_state *
allocatestate(unsigned type)491*672e1225SConrad Meyer allocatestate(unsigned type)
492*672e1225SConrad Meyer {
493*672e1225SConrad Meyer size_t asize;
494*672e1225SConrad Meyer
495*672e1225SConrad Meyer /* No point using this interface to get the Park-Miller LCG. */
496*672e1225SConrad Meyer if (type < TYPE_1)
497*672e1225SConrad Meyer abort();
498*672e1225SConrad Meyer /* Clamp to widest supported variant. */
499*672e1225SConrad Meyer if (type > (MAX_TYPES - 1))
500*672e1225SConrad Meyer type = (MAX_TYPES - 1);
501*672e1225SConrad Meyer
502*672e1225SConrad Meyer asize = sizeof(struct __random_state) + (size_t)breaks[type];
503*672e1225SConrad Meyer return (malloc(asize));
504*672e1225SConrad Meyer }
505