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