Yet another pseudo-random number generator
Moshe Braner
braner at batcomputer.tn.cornell.edu
Sat Feb 11 06:58:39 AEST 1989
/*
* Generate random integers using the shift-register algorithm.
* Copyright Moshe Braner, Nov. 1987. All rights reserved.
* Permission granted for noncommercial usage.
*
* The algorithm here is basically x[i] = x[i-31] EOR x[i-7].
* (Could possibly improve by using x[i] = x[i-127] EOR x[i-63]?)
* Each x[i] here is 32 bits wide, could also be 16 or whatever.
*/
/* "#define FRAND" to include the floating-point stuff */
static long gla[31]; /* array of randoms to shift */
static int glf=1; /* seeding flag */
static long *glp, *glq, *gls, *glt; /* pointers to shift register */
#ifdef FRAND
static double glfm;
#endif
/*
* Seed ran5 - always do this first.
* The seed is any positive integer.
*/
void
sran5(seed)
int seed;
{
register int i;
register long x;
x = (long) seed;
for(i=0; i<100; i++)
x = 31821*x+1;
for(i=0; i<31; i++) {
x = 31821*x+1;
gla[i] = x;
}
glf = 0;
gls = &gla[0];
glp = &gla[0];
glq = &gla[24];
glt = &gla[31];
#ifdef FRAND
glfm = 1.0;
for (i=0; i<31; i++)
glfm *= 0.5; /* EXACTLY 2^(-31) */
#endif
}
/*
* The basic ran5() generator, which returns
* a long integer uniform between 0 and 2^31-1.
*/
long
ran5()
{
register long x, y;
/* short form:
x = ((*glp) ^ (*glq));
if (++glp == glt)
glp = gls;
if (++glq == glt)
glq = gls;
return (x & 0x7FFFFFFF);
safer form: */
if (glf)
sran5(0);
y = x = ((*glp) ^ (*glq)); /* here FORTRAN dies */
x <<= 1;
if (y < 0)
x += 1; /* wish C had a 'rotate' operation */
*glp = x;
if (++glp == glt)
glp = gls;
if (++glq == glt)
glq = gls;
return (y & 0x7FFFFFFF);
}
#ifdef FRAND
/*
* The floating-point ran5() generator.
* Returns a double uniform on [0.0,1.0).
*/
double
fran5()
{
return ((double)ran5() * glfm);
}
#endif FRAND
More information about the Comp.lang.c
mailing list