jrl@anuck.UUCP (j.r.lupien) (02/25/88)
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 */