/*
*    minseed(s);
*    i = minrand();
* This  is the "minimal standard random" routine by Stephen K.  Park and Keith
* W. Miller, in "Random number generators: good ones are hard to find", in the
* Oct  1988 CACM (v.31, no.10).  The authors make a good case that this is the
* minimally-acceptable pseudorandom-number generator for most applications, as
* it  is highly random by all common statistical tests, and has a sufficiently
* long period (2^31-2) for almost all applications. They suggest installing in
* in  all  libraries  in place of the (usually deficient) routines supplied by
* most vendors, and to use an alternate routine only if  it  is  KNOWN  to  be
* better.   If  you can't get at your libraries, you can at least compile this
* routine and use it in your own applications.
*
* You are encouraged to give this source code to anyone who wants it. There is
* no copyright.  It was typed in by John Chambers in C while reading the above
* article.   I don't want to claim credit for what is essentially a  beginning
* coding  task, and I don't think the authors will make any claims on the code
* as long as we continue to give them credit.
*
* This version returns a long int in the range [1..2147483646].
*
* Any long int in the range [1..2147483646] may be used as a seed.  To  get  a
* unique   sequence,   use   an   initialization   like  minseed(getpid())  or
* minseed(time(0L)). For a reproducible sequence, ask the user for a seed, and
* encourage them to use something memorable like their Social Security number.
* Do not use zero, as the result will be a sequence of all zeroes.  Note  that
* the upper bound is 0x7FFFFFFE, which you may find easier to type.
*
* If  compiled  with -DTEST, a test driver is compiled that performs the check
* they suggest of starting with seed=1, calculating 10,000 random numbers, and
* verifying  the resulting seed.  I'd suggest running the test program via the
* command:
*    time minrand
* and dividing the results by 10,000. This gives you approximately the time to
* make one minrand() call.
*
* This program is also useful:  If called with numbers on the command line, it
* will print out a pseudo-random number mod each one.  Thus the command:
*    minrand 50 100
* will give output like:
*    27
*    81
*/
#include "minrand.h"	/* Validate our external declarations */

#define A 16807			/* Multiplier */
#define M 2147483647	/* Modulus */
#define Q 127773		/* M / A */
#define R 2836			/* M % A */

long prevrand = 1;

void minseed(s) long s; { prevrand = s; }

long
minrand()
{	long lo, hi, test;

	hi = prevrand / Q;
	lo = prevrand % Q;
	test = (A * lo) - (R * hi);
	prevrand = (test > 0)? test: test + M;
	return prevrand;
}
#ifdef TEST
#include "V.h"
#define testseed 1043618065	/* Seed 10,001 */

main(ac,av)
	int    ac;
	char **av;
{	int a, n;

	if (ac <= 1) {
		for (n=1; n<=10000; n++)
			minrand();
		if (prevrand == testseed)
			 fprintf(stderr,"The 10,001st seed is correct: %ld.\n",prevrand);
		else fprintf(stderr,"The 10,001st seed is incorrect: %ld.\n",prevrand);
	} else {
		minseed(UnixTime(0L)+getpid());
	}
	for (a=1; a<ac; a++) {
		if (isdigit(av[a][0])) {
			n = atoi(av[a]);
			if (n > 0) {
				printf("%d\n",minrand() % n);
			}
		}
	}
	exit(prevrand != testseed);
}
#endif
