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$"); 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{ 86252698Sache u_long val; 87252698Sache int r; 88252698Sache 89252698Sache#ifdef USE_WEAK_SEEDING 90252698Sache val = *ctx; 91252698Sache#else 92252608Sache /* Transform to [1, 0x7ffffffe] range. */ 93252698Sache val = (*ctx % 0x7ffffffe) + 1; 94252608Sache#endif 95252698Sache r = do_rand(&val); 96110236Sache 97252648Sache#ifdef USE_WEAK_SEEDING 98252648Sache *ctx = (unsigned int)val; 99252648Sache#else 100252648Sache *ctx = (unsigned int)(val - 1); 101252648Sache#endif 102110236Sache return (r); 10347474Swes} 10447474Swes 10547474Swes 106252668Sachestatic u_long next = 107252668Sache#ifdef USE_WEAK_SEEDING 108252668Sache 1; 109252668Sache#else 110252668Sache 2; 111252668Sache#endif 1121573Srgrimes 1131573Srgrimesint 1141573Srgrimesrand() 1151573Srgrimes{ 116110421Sache return (do_rand(&next)); 1171573Srgrimes} 1181573Srgrimes 1191573Srgrimesvoid 1201573Srgrimessrand(seed) 1211573Srgrimesu_int seed; 1221573Srgrimes{ 1231573Srgrimes next = seed; 124252608Sache#ifndef USE_WEAK_SEEDING 125252608Sache /* Transform to [1, 0x7ffffffe] range. */ 126252608Sache next = (next % 0x7ffffffe) + 1; 127252608Sache#endif 1281573Srgrimes} 12947474Swes 13075845Sache 13175845Sache/* 13275845Sache * sranddev: 13375845Sache * 13475845Sache * Many programs choose the seed value in a totally predictable manner. 135249035Sdelphij * This often causes problems. We seed the generator using pseudo-random 136249035Sdelphij * data from the kernel. 13775845Sache */ 13875845Sachevoid 13975845Sachesranddev() 14075845Sache{ 141249035Sdelphij int mib[2]; 142249035Sdelphij size_t len; 14375845Sache 144249035Sdelphij len = sizeof(next); 14575845Sache 146249035Sdelphij mib[0] = CTL_KERN; 147249035Sdelphij mib[1] = KERN_ARND; 148249035Sdelphij sysctl(mib, 2, (void *)&next, &len, NULL, 0); 149252608Sache#ifndef USE_WEAK_SEEDING 150252608Sache /* Transform to [1, 0x7ffffffe] range. */ 151252608Sache next = (next % 0x7ffffffe) + 1; 152252608Sache#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