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