Improved Random by Doug Gwyn

j.r.lupien jrl at anuck.UUCP
Thu Feb 25 09:51:04 AEST 1988


Doug Gwyn posted a nice random number generator based on
one of the Knuth algorithms. His C code was terse to
the extreme, so I have made it a bit more "real".

-------begin file random.c---------
/* random library routines from Doug Gwyn, updated        */
/* 2-24-88 by (jrl) to improve C'ness, UNIX(tm)'ability,  */
/* MS-DOS(tm)'ability, and generally make them a bit      */
/* more randomly usable.                                  */
/* WARNING: assumes 4 byte longs. Will bomb otherwise.    */
/* I am explicitly placing this code in the public domain.*/

#include <stdio.h>
#include <fcntl.h>
#define UNIX 1
#define MSDOS 0

static long ranarray[55] = 
{
	13L,
	447907091L,
	303212375L,
	1090237216L,
	76478184L,
	1335854564L,
	1836462140L,
	998312282L,
	129659655L,
	171330476L,
	1678314018L,
	1179366043L,
	245338699L,
	574023351L,
	1554546701L,
	1058672697L,
	1244784933L,
	241300892L,
	563567664L,
	339155145L,
	533267801L,
	496895778L,
	910037448L,
	1357299517L,
	1659026191L,
	1815742442L,
	22693488L,
	917096309L,
	1672174323L,
	1695320257L,
	155449398L,
	1699460684L,
	344768410L,
	957036558L,
	1252491244L,
	900383150L,
	1208462725L,
	225586921L,
	273530946L,
	248768687L,
	1375739725L,
	726395413L,
	407826567L,
	119597254L,
	711416111L,
	658750653L,
	1313866751L,
	774035896L,
	521958587L,
	65843842L,
	1696715897L,
	1680789672L,
	693748236L,
	230669171L,
	107149589L
};

static int idx1=54;
static int idx2=23;

/*
  As posted by Doug, this would not work on many machines, 
  and might well crash and burn
  on others. The problem was in the pointers. Why don't we just use
  rand() to initialize ranrarray. That way it will at least have
  a good chance of running every time. Better yet, let's have
  ranarray initialized to a set of random numbers generated by 
  random() after a considerable settling time (as above).
  Then people can call initrandom if they feel the need,
  or leave things alone.

*/

void initrandom()
{       
	int i;
	int flags;
	int seed;
	char buf[1];
	/* remove these 5 lines if your code runs. */
	if (sizeof(long) != 4)
	{
		printf("Fix longs first.\n");
		exit(1);
	}
	/*
	   Well, I just can't leave good enough alone.
	   Here is my favorite random seed generator.
	   The MSDOS version depends on the use of MSC
	   or DeSmet. If you lack these, find a substitute
	   for kbhit() if your compiler does not have one.
	*/
#if UNIX
	flags = fcntl(0, F_GETFL, 0);   /* get input flags */
	fcntl(0, F_SETFL, (flags|O_NDELAY));
#endif
	printf("Wait a bit, then type <return> when ready->\n");
	while(1)
	{
#if UNIX
		if (read(0, buf, 1) != 0)
#endif
#if MSDOS
		if (kbhit() != 0)
#endif
		{
			break;
		}
		seed++;
	}
	fcntl(0, F_SETFL, flags);
	srand(seed);
        for (i=0;i<55;i++)
	{
		ranarray[i] += rand();
	}
        ranarray[0]=13L;         /* array must have one odd val */
}

long random(maxval)    /* Return psuedorandom val mod maxval */
long maxval;
{
	/* remove these 5 lines if your code runs. */
	if (sizeof(long) != 4)
	{
		printf("Fix longs first.\n");
		exit(1);
	}
        maxval= (ranarray[idx1--]+=ranarray[idx2--])%maxval;
        if(idx2<0) idx2=54;
        if(idx1<0) idx1=54;
        return ((maxval<0L)?(-maxval):maxval);
}

/* end of file random.c  */



More information about the Comp.lang.c mailing list