looking for uniformly distributed (0..1] random number generator
Eliot Moss
moss at cs.umass.edu
Mon Feb 4 07:13:08 AEST 1991
... and here's our version, based on the same source (Note: a previous posting
of mine had some of the citation information wrong, which I have now corrected
below) .... Eliot
------------------------------------------------------------------------
/*
$RCSfile: random.h,v $
$Revision: 1.3 $
$Date: 90/01/21 14:08:34 $
$Author: moss $
$State: Exp $
$Locker: moss $
*/
/* header file for random.c */
# ifndef __RANDOM__
# define __RANDOM__
# ifdef __STDC__
extern double Random(void); /* Random Generator */
extern int RandomInt(int modulus); /* Returns integer 0 <= r < modulus */
extern int TimeRandomize(void); /* Assign seeds using the system time */
extern int SetRandomSeeds(int s1,int s2); /* Assign seeds. */
# else
extern double Random(); /* Random Generator */
extern int RandomInt(); /* Returns integer 0 <= r < modulus */
extern int TimeRandomize(); /* Assign seeds using the system time */
extern int SetRandomSeeds(); /* Assign seeds. */
# endif
# endif
------------------------------------------------------------------------
/*
$RCSfile: random.c,v $
$Revision: 1.3 $
$Date: 90/01/19 06:42:14 $
$Author: nayeri $
$State: Exp $
$Locker: moss $
*/
/*
*
* random.h Random Generator routines for 32-bit machines.
* Author Farshad Nayeri
* Date July 15, 1989
* Description These are a set of library routines for
* random generation. With the current constants
* the period is about 2E18.
* Disclaimer
* The following routines are correct to the best
* of my knowledge, however I will not responsible
* for direct or indirect implications of using these
* routines in case of any error.
* See Also
* "Efficient and Portable Combined Random Number
* Generators" by Pierre L'Ecuyer, Comm. of ACM,
* Vol 31, Number 6, June 1988.
*
*/
#ifdef VMS
# include <time.h>
#else
# include <sys/types.h>
# include <sys/timeb.h>
#endif
#define NORMAL 0
#define ERROR (-1) /* TimeRandomize depeneds on this value */
#define MAX(s1,s2) ((s1) > (s2) ? (s1) : (s2))
#define MIN(s1,s2) ((s1) < (s2) ? (s1) : (s2))
#define MINSEED1 1
#define MAXSEED1 2147483562
#define DIVISOR1 53668 /* constants for random */
#define SEED1KMULT 40014 /* generator */
#define K1MULT 12211
#define MINSEED2 1
#define DIVISOR2 52274
#define MAXSEED2 2147483398
#define SEED2KMULT 40692
#define K2MULT 3791
#define TIMEFACTOR 10000
double normalizer = (1.0 / ((double)MAX(MAXSEED1,MAXSEED2)));
/* normalization factor */
double maxSeed1and2 = MAX(MAXSEED1,MAXSEED2);
static int seed1 = MAXSEED1 / 2 , /* first and second seed*/
seed2 = MAXSEED2 / 2;
/*
*
* DESCRIPTION
* Random will return a random double precision real value
* between 0.0 and 1.0 (See Efficient and Portable Combined
* Random Number Generators by Pierre L'Ecuyer, Comm. of ACM,
* Vol 31, Number 6, June 1988. )
* NOTES
* This is a 32-bit generator.
*/
# ifdef __STDC__
double Random(void)
# else
double Random()
# endif
{
int z,k;
k = seed1 / DIVISOR1;
seed1 = SEED1KMULT * ( seed1 - k * DIVISOR1) - k * K1MULT;
if (seed1 < 0) seed1 += MAXSEED1 + 1;
/* seed1 = seed1 + MAXSEED1 + 1 */
k = seed2 / DIVISOR2;
seed2 = SEED2KMULT * ( seed2 - k * DIVISOR2) - k * K2MULT;
if (seed2 < 0) seed2 += MAXSEED2 + 1;
/* seed2 = seed2 + MAXSEED2 + 1 */
z = seed1 - seed2;
if (z < 1) z += maxSeed1and2;
return ((double) z * normalizer);
}
/*
*
* DESCRIPTION
* RandomInt returns a random integer between 0 and the modulus-1
* Since Random only returns values r > 0, 1-r < 1, so
* this function will always return values between 0 and modulus-1
*
*/
# ifdef __STDC__
int RandomInt(int modulus)
# else
int RandomInt(modulus)
int modulus;
# endif
{
return((int) ((1.0 - Random()) * modulus));
}
/*
*
* DESCRIPTION
* If s1 and s2 are valid, set the seeds, otherwise returns
* error and keep the old seeds.
* RETURN VALUE
* 0 if everything is O.K.
* -1 if there is an error.
*
*/
# ifdef __STDC__
int SetRandomSeeds(int s1,int s2)
# else
int SetRandomSeeds(s1,s2)
int s1;
int s2;
# endif
{
if ((s1>=MINSEED1) && (s1<=MAXSEED1))
seed1 = s1;
else {
return(ERROR);
}
if ((s2>=MINSEED2) && (s2<=MAXSEED2))
seed2 = s2;
else {
return(ERROR);
}
return(NORMAL);
}
/*
*
* DESCRIPTION
* Use the system time to set the seeds.
* RETURN VALUE
* 0 if everything is O.K.
* -1 if there is a problem with time routine.
*
*/
# ifdef __STDC__
int TimeRandomize(void)
# else
int TimeRandomize()
# endif
{
unsigned short theTime = 0;
struct timeb tp;
ftime(&tp);
theTime = tp.millitm / 10; /* millitm is always multiple of 10 */
if ((theTime & 001) == 0)
SetRandomSeeds((int)(MIN(seed1,seed2) + theTime * TIMEFACTOR)
% MAXSEED1 + MINSEED1,
(int)(MAX(seed1,seed2) % MAXSEED2 + MINSEED2));
else
SetRandomSeeds((int)(MAX(seed1,seed2) + theTime * TIMEFACTOR)
% MAXSEED1 + MINSEED1,
(int)(MIN(seed1,seed2) % MAXSEED2 + MINSEED2));
return(NORMAL);
}
------------------------------------------------------------------------
--
J. Eliot B. Moss, Assistant Professor
Department of Computer and Information Science
Lederle Graduate Research Center
University of Massachusetts
Amherst, MA 01003
(413) 545-4206, 545-1249 (fax); Moss at cs.umass.edu
More information about the Comp.unix.programmer
mailing list