rand.c revision 252668
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.
13251672Semaste * 3. 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: head/lib/libc/stdlib/rand.c 252668 2013-07-04 00:02:10Z ache $");
371573Srgrimes
38108625Stjr#include "namespace.h"
39249035Sdelphij#include <sys/param.h>
40249035Sdelphij#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
70252608Sache	/* 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;
76252608Sache	*ctx = x;
77252608Sache	/* Transform to [0, 0x7ffffffd] range. */
78252608Sache	return (x - 1);
7973156Sache#endif  /* !USE_WEAK_SEEDING */
8047474Swes}
8147474Swes
8247474Swes
8347474Swesint
8447474Swesrand_r(unsigned int *ctx)
8547474Swes{
8647474Swes	u_long val = (u_long) *ctx;
87252608Sache#ifndef USE_WEAK_SEEDING
88252608Sache	/* Transform to [1, 0x7ffffffe] range. */
89252608Sache	val = (val % 0x7ffffffe) + 1;
90252608Sache#endif
91110236Sache	int r = do_rand(&val);
92110236Sache
93252648Sache#ifdef  USE_WEAK_SEEDING
94252648Sache	*ctx = (unsigned int)val;
95252648Sache#else
96252648Sache	*ctx = (unsigned int)(val - 1);
97252648Sache#endif
98110236Sache	return (r);
9947474Swes}
10047474Swes
10147474Swes
102252668Sachestatic u_long next =
103252668Sache#ifdef  USE_WEAK_SEEDING
104252668Sache    1;
105252668Sache#else
106252668Sache    2;
107252668Sache#endif
1081573Srgrimes
1091573Srgrimesint
1101573Srgrimesrand()
1111573Srgrimes{
112110421Sache	return (do_rand(&next));
1131573Srgrimes}
1141573Srgrimes
1151573Srgrimesvoid
1161573Srgrimessrand(seed)
1171573Srgrimesu_int seed;
1181573Srgrimes{
1191573Srgrimes	next = seed;
120252608Sache#ifndef USE_WEAK_SEEDING
121252608Sache	/* Transform to [1, 0x7ffffffe] range. */
122252608Sache	next = (next % 0x7ffffffe) + 1;
123252608Sache#endif
1241573Srgrimes}
12547474Swes
12675845Sache
12775845Sache/*
12875845Sache * sranddev:
12975845Sache *
13075845Sache * Many programs choose the seed value in a totally predictable manner.
131249035Sdelphij * This often causes problems.  We seed the generator using pseudo-random
132249035Sdelphij * data from the kernel.
13375845Sache */
13475845Sachevoid
13575845Sachesranddev()
13675845Sache{
137249035Sdelphij	int mib[2];
138249035Sdelphij	size_t len;
13975845Sache
140249035Sdelphij	len = sizeof(next);
14175845Sache
142249035Sdelphij	mib[0] = CTL_KERN;
143249035Sdelphij	mib[1] = KERN_ARND;
144249035Sdelphij	sysctl(mib, 2, (void *)&next, &len, NULL, 0);
145252608Sache#ifndef USE_WEAK_SEEDING
146252608Sache	/* Transform to [1, 0x7ffffffe] range. */
147252608Sache	next = (next % 0x7ffffffe) + 1;
148252608Sache#endif
14975845Sache}
15075845Sache
15175845Sache
15247474Swes#ifdef TEST
15347474Swes
15447474Swesmain()
15547474Swes{
15647474Swes    int i;
15747474Swes    unsigned myseed;
15847474Swes
15947474Swes    printf("seeding rand with 0x19610910: \n");
16047474Swes    srand(0x19610910);
16147474Swes
16247474Swes    printf("generating three pseudo-random numbers:\n");
16347474Swes    for (i = 0; i < 3; i++)
16447474Swes    {
16547474Swes	printf("next random number = %d\n", rand());
16647474Swes    }
16747474Swes
16847474Swes    printf("generating the same sequence with rand_r:\n");
16947474Swes    myseed = 0x19610910;
17047474Swes    for (i = 0; i < 3; i++)
17147474Swes    {
17247474Swes	printf("next random number = %d\n", rand_r(&myseed));
17347474Swes    }
17447474Swes
17547474Swes    return 0;
17647474Swes}
17747474Swes
17847474Swes#endif /* TEST */
17947474Swes
180