11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1990, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 4. Neither the name of the University nor the names of its contributors
141573Srgrimes *    may be used to endorse or promote products derived from this software
151573Srgrimes *    without specific prior written permission.
161573Srgrimes *
171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271573Srgrimes * SUCH DAMAGE.
2847474Swes *
2947474Swes * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>.
301573Srgrimes */
311573Srgrimes
321573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
331573Srgrimesstatic char sccsid[] = "@(#)rand.c	8.1 (Berkeley) 6/14/93";
341573Srgrimes#endif /* LIBC_SCCS and not lint */
3592986Sobrien#include <sys/cdefs.h>
3692986Sobrien__FBSDID("$FreeBSD$");
371573Srgrimes
38108625Stjr#include "namespace.h"
39251168Sdelphij#include <sys/param.h>
40251168Sdelphij#include <sys/sysctl.h>
411573Srgrimes#include <sys/types.h>
421573Srgrimes#include <stdlib.h>
4375863Sache#include "un-namespace.h"
441573Srgrimes
4547474Swes#ifdef TEST
4647474Swes#include <stdio.h>
4747474Swes#endif /* TEST */
4847474Swes
4947474Swesstatic int
5047474Swesdo_rand(unsigned long *ctx)
5147474Swes{
5273156Sache#ifdef  USE_WEAK_SEEDING
5373156Sache/*
5473156Sache * Historic implementation compatibility.
5573156Sache * The random sequences do not vary much with the seed,
5673156Sache * even with overflowing.
5773156Sache */
5847474Swes	return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
5973156Sache#else   /* !USE_WEAK_SEEDING */
6073156Sache/*
6173156Sache * Compute x = (7^5 * x) mod (2^31 - 1)
62174541Sache * without overflowing 31 bits:
6373156Sache *      (2^31 - 1) = 127773 * (7^5) + 2836
6473156Sache * From "Random number generators: good ones are hard to find",
6573156Sache * Park and Miller, Communications of the ACM, vol. 31, no. 10,
6673156Sache * October 1988, p. 1195.
6773156Sache */
6873156Sache	long hi, lo, x;
6973156Sache
70253607Sache	/* Must be in [1, 0x7ffffffe] range at this point. */
7173156Sache	hi = *ctx / 127773;
7273156Sache	lo = *ctx % 127773;
7373156Sache	x = 16807 * lo - 2836 * hi;
74110280Sache	if (x < 0)
7573156Sache		x += 0x7fffffff;
76253607Sache	*ctx = x;
77253607Sache	/* Transform to [0, 0x7ffffffd] range. */
78253607Sache	return (x - 1);
7973156Sache#endif  /* !USE_WEAK_SEEDING */
8047474Swes}
8147474Swes
8247474Swes
8347474Swesint
8447474Swesrand_r(unsigned int *ctx)
8547474Swes{
86253607Sache	u_long val;
87253607Sache	int r;
88110236Sache
89253607Sache#ifdef  USE_WEAK_SEEDING
90253607Sache	val = *ctx;
91253607Sache#else
92253607Sache	/* Transform to [1, 0x7ffffffe] range. */
93253607Sache	val = (*ctx % 0x7ffffffe) + 1;
94253607Sache#endif
95253607Sache	r = do_rand(&val);
96253607Sache
97253607Sache#ifdef  USE_WEAK_SEEDING
98253607Sache	*ctx = (unsigned int)val;
99253607Sache#else
100253607Sache	*ctx = (unsigned int)(val - 1);
101253607Sache#endif
102110236Sache	return (r);
10347474Swes}
10447474Swes
10547474Swes
106253607Sachestatic u_long next =
107253607Sache#ifdef  USE_WEAK_SEEDING
108253607Sache    1;
109253607Sache#else
110253607Sache    2;
111253607Sache#endif
1121573Srgrimes
1131573Srgrimesint
1141573Srgrimesrand()
1151573Srgrimes{
116110421Sache	return (do_rand(&next));
1171573Srgrimes}
1181573Srgrimes
1191573Srgrimesvoid
1201573Srgrimessrand(seed)
1211573Srgrimesu_int seed;
1221573Srgrimes{
1231573Srgrimes	next = seed;
124253607Sache#ifndef USE_WEAK_SEEDING
125253607Sache	/* Transform to [1, 0x7ffffffe] range. */
126253607Sache	next = (next % 0x7ffffffe) + 1;
127253607Sache#endif
1281573Srgrimes}
12947474Swes
13075845Sache
13175845Sache/*
13275845Sache * sranddev:
13375845Sache *
13475845Sache * Many programs choose the seed value in a totally predictable manner.
135251168Sdelphij * This often causes problems.  We seed the generator using pseudo-random
136251168Sdelphij * data from the kernel.
13775845Sache */
13875845Sachevoid
13975845Sachesranddev()
14075845Sache{
141251168Sdelphij	int mib[2];
142251168Sdelphij	size_t len;
14375845Sache
144251168Sdelphij	len = sizeof(next);
14575845Sache
146251168Sdelphij	mib[0] = CTL_KERN;
147251168Sdelphij	mib[1] = KERN_ARND;
148251168Sdelphij	sysctl(mib, 2, (void *)&next, &len, NULL, 0);
149253607Sache#ifndef USE_WEAK_SEEDING
150253607Sache	/* Transform to [1, 0x7ffffffe] range. */
151253607Sache	next = (next % 0x7ffffffe) + 1;
152253607Sache#endif
15375845Sache}
15475845Sache
15575845Sache
15647474Swes#ifdef TEST
15747474Swes
15847474Swesmain()
15947474Swes{
16047474Swes    int i;
16147474Swes    unsigned myseed;
16247474Swes
16347474Swes    printf("seeding rand with 0x19610910: \n");
16447474Swes    srand(0x19610910);
16547474Swes
16647474Swes    printf("generating three pseudo-random numbers:\n");
16747474Swes    for (i = 0; i < 3; i++)
16847474Swes    {
16947474Swes	printf("next random number = %d\n", rand());
17047474Swes    }
17147474Swes
17247474Swes    printf("generating the same sequence with rand_r:\n");
17347474Swes    myseed = 0x19610910;
17447474Swes    for (i = 0; i < 3; i++)
17547474Swes    {
17647474Swes	printf("next random number = %d\n", rand_r(&myseed));
17747474Swes    }
17847474Swes
17947474Swes    return 0;
18047474Swes}
18147474Swes
18247474Swes#endif /* TEST */
18347474Swes
184