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