/*
 * Copyright (c) 1994 by Landon Curt Noll.  All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright, this permission notice and text
 * this comment, and the disclaimer below appear in all of the following:
 *
 *	supporting documentation
 *	source copies
 *	source works derived from this source
 *	binaries derived from this source or from derived source
 *
 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Prior to calc 2.9.3t9, these routines existed as a calc library called
 * cryrand.cal.  They have been rewritten in C for performance as well
 * as to make them available directly from libcalc.a.
 *
 * Comments, suggestions, bug fixes and questions about these routines
 * are welcome.  Send EMail to the address given below.
 *
 * Happy bit twiddling,
 *
 *			Landon Curt Noll
 *
 *			chongo@toad.com
 *			...!{pyramid,sun,uunet}!hoptoad!chongo
 *
 * chongo was here	/\../\
 */

/*
 * XXX - Be sure that lambda(n) = lcm(factors of p-1 & q-1) is large
 *	 for the default case.
 *
 * XXX - discuss lambda(n)
 *
 * XXX - When selecting a random prime for Maurer's method, do not jump into
 *	 the table and sweep upward as this will bias for primes that follow
 *	 large gaps.
 *
 * XXX - need isrand() and israndom()
 *
 * XXX - Add shs() and md5 hash functions.  Ensure that any object can
 *	 be hashed.  Ensure that if a == b, hash of a == hash of b.
 *	 This can be done by hashing all values of an value that
 *	 are used in the equality test.  Note that the value type should
 *	 also be hashed to help distinguish different value types.
 *	 Also note that objects should hash their name.  The shs() and
 *	 md5() should NOT replace the foohash() functions used by
 *	 associative arrays as those functions need to be fast.
 *
 * XXX - write rand() and srand() help pages
 *
 * XXX - write random() and srandom() help pages
 *
 * XXX - update help/todo
 */

/*
 * AN OVERVIEW OF THE FUNCTIONS:
 *
 * This module contains two pseudo-random number generators:
 *
 *   Additive 55 shuffle generator:
 *
 *	We refer to this generator as the a55 generator.
 *
 *	rand	- a55 shuffle generator
 *	srand	- seed the a55 shuffle generator
 *
 *	This generator has two distinct parts, the a55 generator
 *	and the shuffle generator.
 *
 *	The additive 55 generator is described in Knuth's "The Art of
 *	Computer Programming - Seminumerical Algorithms", Vol 2, 2nd edition
 *	(1981), Section 3.2.2, page 27, Algorithm A.
 *
 *	The period and other properties of this generator make it very
 *	useful to 'seed' other generators.
 *
 *	The shuffle generator is described in Knuth's "The Art of Computer
 *	Programming - Seminumerical Algorithms", Vol 2, 2nd edition (1981),
 *	Section 3.2.2, page 32, Algorithm B.
 *
 *	The shuffle generator is fast and serves as a fairly good standard
 *	pseudo-random generator.   If you need a fast generator and do not
 *	need a cryptographically strong one, this generator is likely to do
 *	the job.
 *
 *	The shuffle generator is feed values by the additive 55 process.
 *
 *   Blum-Blum-Shub generator:
 *
 *	We refer to this generator as the Blum generator.
 *
 *	This generator is described in the papers:
 *
 *	    Blum, Blum, and Shub, "Comparison of Two Pseudorandom Number
 *	    Generators", in Chaum, D. et. al., "Advances in Cryptology:
 *	    Proceedings Crypto 82", pp. 61-79, Plenum Press, 1983.
 *
 *	    Blum, Blum, and Shub, "A Simple Unpredictable Pseudo-Random
 *	    Number Generator", SIAM Journal of Computing, v. 15, n. 2,
 *	    1986, pp. 364-383.
 *
 *	    U. V. Vazirani and V. V. Vazirani, "Trapdoor Pseudo-Random
 *	    Number Generators with Applications to Protocol Design",
 *	    Proceedings of the 24th  IEEE Symposium on the Foundations
 *	    of Computer Science, 1983, pp. 23-30.
 *
 *	    U. V. Vazirani and V. V. Vazirani, "Efficient and Secure
 *	    Pseudo-Random Number Generation", Proceedings of the 24th
 *	    IEEE Symposium on the Foundations of Computer Science,
 *	    1984, pp. 458-463.
 *
 *	    U. V. Vazirani and V. V. Vazirani, "Efficient and Secure
 *	    Pseudo-Random Number Generation", Advances in Cryptology -
 *	    Proceedings of CRYPTO '84, Berlin: Springer-Verlag, 1985,
 *	    pp. 193-202.
 *
 *	    "Probabilistic Encryption", Journal of Computer & System
 *	    Sciences 28, pp. 270-299.
 *
 *	    Bruce Schneier, "Applied Cryptography", John Wiley & Sons,
 *	    1st edition (1994), pp 365-366.
 *
 *	This generator is considered 'strong' in that it passes all
 *	polynomial-time statistical tests.  The sequences produced
 *	are random in an absolutely precise way.  There is absolutely
 *	no better way to predict the sequence than by tossing a coin
 *	(as with TRULY random numbers) EVEN IF YOU KNOW THE MODULUS!
 *	Furthermore, having a large chunk of output from the sequence
 *	does not help.  The BITS THAT FOLLOW OR PRECEDE A SEQUENCE
 *	ARE UNPREDICTABLE!
 *
 *	To compromise the generator, an adversary must either factor the
 *	modulus or perform an exhaustive search just to determine the next
 *	(or previous) bit.  If we make the modulus hard to factor
 *	(such as the product of two large well chosen primes) breaking
 *	the sequence could be intractable for todays computers and methods.
 */

/*
 * ON THE GENERATORS:
 *
 * The additive 55 generator has a good period, and is fast.  It is
 * reasonable as generators go, though there are better ones available.
 * The shuffle generator has a very good period, and is fast.  It is
 * fairly good as generators go, particularly when it is feed reasonably
 * random numbers.  Because of this, we use feed values from the additive
 * 55 process into the shuffle generator.
 *
 * The a55 generator uses 2 tables:
 *
 *	additive table - 55 entries of 64 bits used by the additive 55
 *			 part of the a55 generator
 *
 *	shuffle table - 256 entries of 64 bits used by the shuffle
 *			part of the a55 generator and feed by the
 *		 	additive table.
 *
 * Casual direct use of the shuffle generator may be acceptable.  If one
 * desires cryptographically strong random numbers, or if one is paranoid,
 * one should use the Blum generator instead.
 *
 * The a55 generator as the following calc interfaces:
 *
 *   rand(min,max)		(where min < max)
 *
 *	Print an a55 generator random value over interval [a,b).
 *
 *   rand()
 *
 *	Same as rand(0, 2^64).  Print 64 bits.
 *
 *   rand(lim)			(where 0 > lim)
 *
 *	Same as rand(0, lim).
 *
 *   randbit(x)			(where x > 0)
 *
 *	Same as rand(0, 2^x).  Print x bits.
 *
 *   randbit(skip)		(where skip < 0)
 *
 *	Skip skip radom bits and return the bit skip count (-skip).
 *
 ***
 *
 * The Blum generator is the best generator in this package.  It
 * produces a cryptographically strong pseudo-random bit sequence.
 * Internally, a fixed number of bits are generated after each
 * generator iteration.  Any unused bits are saved for the next call
 * to the generator.  The Blum generator is not too slow, though
 * seeding the generator via srandom(seed,plen,qlen) can be slow.
 * Shortcuts and pre-computer seeds have been provided for this reason.
 * Use of Blum should be more than acceptable for many applications.
 *
 * The Blum generator as the following calc interfaces:
 *
 *   random(min, max)		(where min < max)
 *   XXX - write this function
 *
 *	Print a Blum generator random value over interval [min,max).
 *
 *   random()
 *   XXX - write this function
 *
 *	Same as random(0, 2^64).  Print 64 bits.
 *
 *   random(lim)		(where 0 > lim)
 *   XXX - write this function
 *
 *	Same as random(0, lim).
 *
 *   randombit(x)		(where x > 0)
 *   XXX - write this function
 *
 *	Same as random(0, 2^x).  Print x bits.
 *
 *   randombit(skip)		(where skip < 0)
 *   XXX - write this function
 *
 *	Skip skip radom bits and return the bit skip count (-skip).
 */

/*
 * INITIALIZATION AND SEEDS:
 *
 * All generators come already seeded with precomputed initial constants.
 * Thus, it is not required to seed a generator before using it.
 *
 * The a55 generator may be initialized and seeded via srand().
 * The Blum generator may be initialized and seeded via srandom().
 *
 * Using a seed of '0' will reload generators with their initial states.
 *
 *	srand(0)	restore additive 55 generator to the initial state
 *	srandom(0)	restore Blum generator to the initial state
 *
 * The above single arg calls are fairly fast.
 *
 * The call:
 *
 *	srandom(seed, newn)
 *
 * is fast when the config value "modchk" is 0, 1 or 2.
 *
 * Optimal seed range for the a55 generator:
 *
 *	There is no limit on the size of a seed.  On the other hand,
 *	extremely large seeds require large tables and long seed times.
 *	Using a seed in the range of [2^64, 2^64 * 55!) should be
 *	sufficient for most purposes.  An easy way to stay within this
 *	range to to use seeds that are between 21 and 77 digits, or
 *	64 to 243 bits long.
 *
 *	To help make the generator produced by seed S, significantly
 *	different from S+1, seeds are scrambled prior to use.  The
 *	function randreseed64() maps [0,2^64) into [0,2^64) in a 1-to-1
 *	and onto fashion.
 *
 *	The purpose of the randreseed64() is not to add security.  It
 *	simply helps remove the human perception of the relationship
 *	between the seed and the production of the generator.
 *
 *	The randreseed64() process does not reduce the security of the
 *	generators.  Every seed is converted into a different unique seed.
 *	No seed is ignored or favored.
 *
 * Optimal seed range for the Blum generator:
 *
 *	There is no limit on the size of a seed.  On the other hand,
 *	in most cases the seed is taken modulo the Blum modulus.
 *	Using a seed that is too small (except for 0) results in
 *	an internal generator be used to increase its size.
 *
 *	It is faster to use seeds that are in the half open internal
 *	[sqrt(n), n) where n is the Blum modulus.
 *
 *	The default Blum modulus is 256 bits.  The default
 *	optimal size of a seed is between 128 and 256 bits.
 *
 *	The exception is when srandom(seed, plen, qlen) is used.
 *	When seed < 0, the seed is given to an internal a55 generator
 *	and the a55 generator range (negated) applies.  When seed > 0,
 *	the seed is given to an internal Blum generator and the
 *	128 to 256 bit range applies.  The value seed == 0 may also
 *	be used in this type of call.
 *
 *****
 *
 * srand(seed)
 *
 *   Seed the a55 generator.
 *
 *   seed != 0:
 *	Any buffered random bits are flushed.  The additive table is loaded
 *	with the default additive table.  The low order 64 bits of seed is
 *	xor-ed against each table value.  The additive table is shuffled
 *	according to seed/2^64.
 *
 *	The following calc code produces the same effect:
 *
 *	    (* reload default additive table xored with low 64 seed bits *)
 *	    seed_xor = seed & ((1<<64)-1);
 *	    for (i=0; i < 55; ++i) {
 *		additive[i] = xor(default_additive[i], seed_xor);
 *	    }
 *
 *	    (* shuffle the additive table *)
 *	    seed >>= 64;
 *	    for (i=55; seed > 0 && i > 0; --i) {
 *		quomod(seed, i+1, seed, j);
 *		swap(additive[i], additive[j]);
 *	    }
 *
 *	Seed must be >= 0.  All seed values < 0 are reserved for future use.
 *
 *	The additive 55 pointers are reset to additive[23] and additive[54].
 *	Last the shuffle table is loaded with successive values from the
 *	additive 55 generator.
 *
 *   seed == 0:
 *	Restore the initial state and modulus of the a55 generator.
 *	After this call, the a55  generator is restored to its initial
 *	state after calc started.
 *
 *	The additive 55 pointers are reset to additive[23] and additive[54].
 *	Last the shuffle table is loaded with successive values from the
 *	additive 55 generator.
 *
 ***
 *
 * srand(mat55)
 *
 *   Seed the a55 generator.
 *
 *   Any buffered random bits are flushed.  The additive table with the
 *   first 55 entries of the array mat55, mod 2^64.
 *
 *   The additive 55 pointers are reset to additive[23] and additive[54].
 *   Last the shuffle table is loaded with successive values from the
 *   additive 55 generator.
 *
 ***
 *
 * srand()
 *
 *   Return current a55 generator state.  This call does not alter
 *   the generator state.
 *
 * srand(state)
 *
 *   Restore the a55 state and return the previous state.  Note that
 *   the argument state is a rand state value (isrand(state) is true).
 *   Any internally buffered random bits are restored.
 *
 * The states of the a55 generators can be saved by calling the seed
 * function with no arguments, and later restored by calling the seed
 * functions with that same return value.
 *
 *	rand_state = srand();
 *
 *	... generate random bits ...
 *
 *	prev_rand_state = srand(rand_state);
 *
 *	... generate the same random bits ...
 *
 *	srand() == prev_rand_state;		(* is true *)
 *
 * Saving the state just after seeding a generator and restoring it later
 * as a very fast way to reseed a generator.
 *
 ***
 *
 * srandom(seed)
 * XXX - write this function
 *
 *   Seed the Blum generator.
 *
 *   Here we assume that the Blum modulus is n.  Any internally buffered
 *   random bits are flushed.
 *
 *   seed >  0:
 *	The quadratic residue is set to seed^2 mod n, unless it is
 *	too small.
 *
 *	The following calc code produces the same quadratic residue:
 *
 *	    (* try to form a reasonable quadratic residue *)
 *	    quadres = pmod(seed, 2, n);
 *
 *	    (* note the [2^sqrpow,n/2) range *)
 *	    lowlim = 1<<(ceil((highbit(n)+1)*3/4));
 *	    highlem = floor(n/2);
 *
 *	    (* determine the distance to the next quadratic residue *)
 *	    nextres = pmod(quadres, 2, n);
 *	    nextdist = abs(nextres - quadres);
 *
 *	    (* avoid too residues that are too small *)
 *	    if (quadres < lowlim || quadres > highlim ||
 *		nextres < lowlim || nextres > highlim ||
 *		nextdist <= lowlim) {
 *
 *	        (* initialize internal a55 generator *)
 *	        srand(seed);
 * XXX - the seed is just a seed, not a random number; explain below
 *
 *		(* form a quadratic residue that is not too small *)
 *		do {
 *		    quadres += pmod(rand(highbit(n)+1), 2, n);
 *	    	    nextres = pmod(quadres, 2, n);
 *		    nextdist = abs(nextres - quadres);
 *		} while (quadres < lowlim || quadres > highlim ||
 *			 nextres < lowlim || nextres > highlim ||
 *			 nextdist <= lowlim);
 *	    }
 *
 *	Note that when seed == 0, the default quadratic	residue is produced
 *	by using an internal a55 generator seeded with the default seed.
 *
 *	Also note that the internal generator that is used to help
 *	generate the quadratic residue is internal to this function only.
 *	It will not impact the use of any other generator.  (The above
 *	code is just an illustration)
 *
 *   seed == 0:
 *	Restore the initial state and modulus of the Blum generator.
 *	After this call, the Blum  generator is restored to its initial
 *	state after calc started.
 *
 *	Note that unlike other forms of srandom(seed), seed == 0 does
 *	change the modulus.
 *
 *	Seed must be >= 0.  All seed values < 0 are reserved for future use.
 *
 *****
 *
 * srandom(seed, newn)
 * XXX - write this function
 *
 *   Seed the Blum generator.
 *
 *   Here we attempt to set the Blum modulus to the value newn.
 *   Any internally buffered random bits are flushed.
 *
 *   The config value "modchk" determines what, if any, sanity
 *   checks are performed on newn:
 *
 *	    0	no checks are performed
 *	    1   require newn to be 1 mod 4
 *	    2	require newn to be 1 mod 4 and to pass ptest(newn,0)
 *		(trivial factor check)
 *	    3	require newn to be 1 mod 4 and to pass ptest(newn,1)
 *		(trivial factor and one probable prime test)
 *	    4	require newn to be 1 mod 4 and to pass ptest(newn,25)
 *		(trivial factor and 25 probable prime test)
 *
 *    The default "modchk" value is 3.  All other values are reserved
 *    for future use.
 *
 *    Once the Blum modulus is set, the call proceeds as:
 *
 *	    srandom(seed)
 *
 ***
 *
 * srandom(state, plen, qlen)
 * XXX - write this function
 *
 *   Seed the Blum generator.
 *
 *   Here we select a Blum modulus using an internal random number
 *   generator depending on the value of seed.  Any internally buffered
 *   random bits are flushed.
 *
 *   The state argument may be a state of another Blum generator or
 *   from an a55 generator.  This state is used to set an internal
 *   random number generator which in turn is used to select Blum primes.
 *
 *   plen > 0 and qlen > 0:
 *
 *      We will use Maurer's method to generate two Blum primes.
 *      The following calc code produces the same two Blum primes:
 *
 *	    (* generate 1st Blum prime 3mod4, plen bits long *)
 *	    p = randprime(2^(plen-1), 2^plen, 3, 4, state);
 *
 *	    (* generate 2nd Blum prime 3mod4, qlen bits long, don't reseed *)
 *	    q = randprime(2^(qlen-1), 2^qlen, 3, 4, state);
 *
 *	    (* generate the Blum modulus *)
 *	    n = p * q;
 *
 *	Next the quadratic residue is selected.  Using the same internal
 *	generator as it was left by the generation of the 2nd Blum prime,
 *	a quadratic residue is formed.  The process of selection is similar
 *	to that of the srandom(seed) process.
 *
 *	Also note that the internal generator that is used to help
 *	generate Blum primes is internal to this function only.  It
 *	will not impact the use of any other generator, including
 *	the one used by randprime.  (The above code is just an illustration)
 *	The value of state is changed, however.
 *
 *   plen == 0 and qlen == 0:
 *
 *	We will use Maurer's method to generate two Blum primes of
 *	default length.  In all other cases this form is identical
 *	to the call:
 *
 *	    srandom(state, 248, 264);
 *
 *	Note that:
 *
 *	    srandom(srandom(0), 0, 0);
 *
 *	is identical to the call:
 *
 *	    srandom(0);
 *
 *   plen < 0 and qlen < 0:
 *
 *	We will generate random probable Blum primes, that is primes
 *	that are 3 mod 4.  The Blum primes selected will be -plen
 *	and -qlen bits long.  Their product will be the Blum modulus.
 *
 *	The state is used to help select probable Blum primes.
 *	Next the quadratic residue is selected.  Using the same internal
 *	generator as it was left by the generation of the 2nd Blum prime,
 *	a quadratic residue is formed.  The process of selection is similar
 *	to that of the srandom(seed) process.
 *
 *	Also note that the internal generator that is used to help
 *	generate Blum primes is internal to this function only.  It
 *	will not impact the use of any other generator, including
 *	the one used by randprime.  (The above code is just an illustration)
 *	The value of state is changed, however.
 *
 ***
 *
 * srandom()
 * XXX - write this function
 *
 *   Return current Blum generator state.  This call does not alter
 *   the generator state.
 *
 * srandom(state)
 * XXX - write this function
 *
 *   Restore the Blum state and return the previous state.  Note that
 *   the argument state is a random state value (israndom(state) is true).
 *   Any internally buffered random bits are restored.
 *
 * The states of the Blum generators can be saved by calling the seed
 * function with no arguments, and later restored by calling the seed
 * functions with that same return value.
 *
 *	random_state = srandom();
 *
 *	... generate random bits ...
 *
 *	prev_random_state = srandom(random_state);
 *
 *	... generate the same random bits ...
 *
 *	srandom() == prev_random_state;		(* is true *)
 *
 * Saving the state just after seeding a generator and restoring it later
 * as a very fast way to reseed a generator.
 */

/*
 * TRUTH IN ADVERTISING:
 *
 * When the call:
 *
 *	srandom(seedlen, plen, qlen)
 *
 * is given plen or qlen < 0, probable primes are used.  We use the word
 * 'probable' because of an extremely extremely small chance that a
 * composite (a non-prime) may be returned.
 *
 * We use the builtin function nextcand in its 5 arg form:
 *
 *	nextcand(ip, 25, 0, 3, 4)
 *
 * The odds that a number returned by the above call is not prime is
 * less than 1 in 4^25.  For our purposes, this is sufficient as the
 * chance of returning a composite is much smaller than the chance that
 * a hardware glitch will cause nextcand() to return a bogus result.
 *
 * Another "truth in advertising" issue is the use of the term
 * 'pseudo-random'.  All deterministic generators are pseudo random.
 * This is opposed to true random generators based on some special
 * physical device.
 *
 * Even though Blum generator is 'pseudo-random', there is no statistical
 * test, which runs in polynomial time, that can distinguish the Blum
 * generator from a truly random source.  See the comment under
 * the "Blum-Blum-Shub generator" section above.
 *
 * A final "truth in advertising" issue deals with how the magic numbers
 * found in this library were generated.  Detains can be found in the
 * various functions, while a overview can be found in the SOURCE FOR
 * MAGIC NUMBERS section below.
 */

/*
 * SOURCE OF MAGIC NUMBERS:
 *
 * Most of the magic constants used on this library ultimately are
 * based on the Rand book of random numbers.  The Rand book contains
 * 10^6 decimal digits, generated by a physical process.  This book,
 * produced by the Rand corporation in the 1950's is considered
 * a standard against which other generators may be measured.
 *
 * The Rand book of numbers was groups into groups of 20 digits.
 * The first 55 groups < 2^64 were used to initialize init_a55.slot.
 * The size of 20 digits was used because 2^64 is 20 digits long.
 * The restriction of < 2^64 was used to prevent modulus biasing.
 * (see the note on  modulus biasing in rand()).
 *
 * The function, randreseed64(), uses 2 primes to scramble 64 bits
 * into 64 bits.  These primes were also extracted from the Rand
 * book of numbers.  See randreseed64() for details.
 *
 * The shuffle table size is longer than the 100 entries recommended
 * by Knuth.  We use a power of 2 shuffle table length so that the
 * shuffle process can select a table entry from a new additive 55
 * value by extracting its low order bits.  The value 256 is conveient
 * in that it is the size of a byte which allows for easy extraction.
 *
 * We use the upper byte of the additive 55 value to select
 * the shuffle table entry because it allows all of 64 bits
 * to play a part in the entry selection.  If we were to
 * select a lower 8 bits in the 64 bit value, carries that
 * proprogate above our 8 bits would not impact the a55
 * generator output.
 *
 * The quadratic residue search performed by the Blum generator starts
 * at a value that is in the interval [2^sqrpow,n/2), where '2^sqrpow'
 * is the smallest power of 2 that is 3/4 the size of the smallest
 * power of 2 >= n, the Blum modulus (n = p*q).  We use the value
 * '3/4 the size of the smallest power of 2 >= n' because this
 * avoids residues near n^1/4, n^1/2, n^1/3 and n^2/3.  While
 * the initial quadratic residue may be more other fractional
 * powers of n (such as n^3/4, n^4/5) these powers are more
 * complex and produce less obvious patterns when squared mod n.
 *
 * The use of '2^sqrpow' insures that the quadratic residue is
 * large, but not too large.  We want to avoid residues that are
 * near 0 or that are near 'n'.  Such residues are trivial or
 * semi-trivial.  Applying the same restriction to the square
 * of the initial residue avoid initial residues near 'sqrt(n)'.
 * Such residues are trivial or semi-trivial as well.
 *
 * We reject any initial residue whose square (mod n) does not fit
 * this same restriction.  We reject any residue that is within
 * 2^sqrpow of its square (mod n).  This helps ensure that we
 * do not enter into a small sequence early.
 *
 * Avoiding residues whose squares (mod n) are not within 2^sqrpow of
 * itself helps avoid selecting residue sequences (repeated
 * squaring mod n) that initially do not change very much.
 * Such residues might be somewhat trivial, so we play it safe.
 *
 * Taking some care to select a good initial residue helps
 * eliminate cheap search attacks.  It is true that a subsequent
 * residue could be one of the residues that we would initially
 * avoid.  However such an occurrence will happen after the
 * generator is well underway and any such information
 * has been lost.
 *
 * XXX - determine minimal size modulus and prime lengths
 *
 * The final magic numbers: '248' and '264' are the exponents the
 * largest powers of 2 that are < the two default Blum primes 'p'
 * and 'q' used by the Blum generator.  The values of '248' and
 * '264' implies that the product n=p*q > 2^512.  Each iteration
 * of the Blum generator produces log2(log2(n=p*q)) random bits.
 * The Blum generator is the most efficient when n is slightly >
 * 2^(2^b).  The product n > 2^(2^9)) produces 9 bits as efficiently
 * as possible under the Blum generator process.
 *
 * Not being able to factor 'n=p*q' into 'p' and 'q' does not directly
 * improve the quality Blum generator.  On the other hand, it does
 * improve the security of it.
 *
 * As we stated above, there is absolutely no better way to predict the
 * sequence than by tossing a coin (as with TRULY random numbers) EVEN
 * IF YOU KNOW THE MODULUS AND WHERE YOU ARE IN THE SEQUENCE!  An
 * adversary would be far better advised to try to factor the modulus
 * and break the sequence that way.   Thus we want to make 'n' hard
 * to factor.
 *
 * The two len values differ slightly to avoid factorization attacks
 * that work on numbers that are a perfect square, or where the two
 * primes are nearly the same.  I elected to have the sizes differ
 * by 3% of the product size.  The difference between '248' and
 * '264', is '16', which is ~3.125% of '512'.  Now 3% of '512' is
 * '~15.36', and the next largest whole number is '16'.
 *
 * The product n=p*q > 2^512 implies a product if at least 155 digits.
 * A product of two primes that is at least 155 digits is slightly
 * beyond Number Theory and computer power of Nov 1992, though this
 * will likely change in the future.
 *
 * Again, the ability (or lack thereof) to factor 'n=p*q' does not
 * directly relate to the strength of the Blum generator.  We
 * selected n=p*q > 2^512 mainly because '512 was a power of 2 and
 * only slightly because it is up in the range where it is difficult
 * to factor.
 *
 ****
 *
 * FOR THE PARANOID:
 *
 * The truly paranoid might suggest that my claims in the MAGIC NUMBERS
 * section are a lie intended to entrap people.  Well they are not, but
 * you need not take my word for it.
 *
 * The random numbers from the Rand book of random numbers can be
 * verified by anyone who obtains the book.  As these numbers were
 * created before I (Landon Curt Noll) was born (you can look up
 * my birth record if you want), I claim to have no possible influence
 * on their generation.
 *
 * There is a very slight chance that the electronic copy of the
 * Rand book that I was given access to differs from the printed text.
 * I am willing to provide access to this electronic copy should
 * anyone wants to compare it to the printed text.
 *
 * One might object to the complexity of the seed scramble/mapping
 * via the randreseed64() function.  The randreseed64() function maps:
 *
 *	1 ==> 4967126403401436567
 *
 * calling srand(1) with the randreseed64() process would be the same
 * as calling srand(4967126403401436567) without it.  No extra security
 * is gained or reduced by using the randreseed64() process.  The meaning
 * of seeds are exchanged, but not lost or favored (used by more than
 * one input seed).
 *
 * One could take issue with my selection of the default sizes '248'
 * and '264'.   As far as I know, 155 digits (512 bits) is beyond the
 * state of the art of Number Theory and Computation as of 01 Jan 95.
 * It will likely be true that 155 digit products of two primes could
 * come within reach in the next few years, but so what?  If you are
 * truly paranoid, why would you want to use the default seed, which
 * is well known?
 *
 * The paranoid today might consider using the lengths of at least '345'
 * and '325' will produce a product of two primes that is 202 digits.
 * (the 2nd and 3rd args of scryrand > 345 & >325 respectively)  Factoring
 * 200+ digit product of two primes is well beyond the current hopes of
 * Number Theory and Computer power, though even this limit may be passed
 * someday.
 *
 * If all the above fails to pacify the truly paranoid, then one may
 * select your own modulus and initial quadratic residue by calling:
 *
 *	srandom(seed, n)
 *
 * when using the Blum generator.  One can even set the config value
 * "modchk" to 0 and avoid my checks.
 *
 * When using the a55 generator, one may select your own 55 additive
 * values by calling:
 *
 *	srand(mat55)
 *
 * and avoid using my magic numbers.  Of course, you must pick good
 * additive 55 values youself!
 *
 ****
 *
 * GOALS:
 *
 * The goals of this package are:
 *
 *	all magic numbers are explained
 *
 *	    I distrust systems with constants (magic numbers) and tables
 *	    that have no justification (e.g., DES).  I believe that I have
 *	    done my best to justify all of the magic numbers used.
 *
 *	 full documentation
 *
 *	    You have this source file, plus background publications,
 *	    what more could you ask?
 *
 *	large selection of seeds
 *
 *	    Seeds are not limited to a small number of bits.  A seed
 *	    may be of any size.
 *
 *	the strength of the generators may be tuned to meet the need
 *
 *	    By using the appropriate seed and other arguments, one may
 *	    increase the strength of the generator to suit the need of
 *	    the application.  One does not have just a few levels.
 *
 * Even though I have done my best to implement a good system, you still
 * must use these routines your own risk.
 *
 * Share and enjoy!  :-)
 */


#include "zrand.h"


/*
 * default a55 generator state
 *
 * This is the state of the a55 generator after initialization, or srand(0),
 * or srand(0) is called.  The init_a55 value is never changed, only copied.
 */
static RAND init_a55 = {
	1,		/* seeded */
	3,		/* j */
	34,		/* k */
	0,		/* no buffered bits */
#if FULL_BITS == SBITS		/* buffer */
	{0},
#elif 2*FULL_BITS == SBITS
	{0, 0},
#else
   /\../\	BASEB is assumed to be 16 or 32 	/\../\   !!!
#endif
	{		/* additive 55 table */
  SVAL(23a252f6, 0bae4907), SVAL(4f4ad31f, 3818af34), SVAL(689806c4, 03319a17),
  SVAL(e6354a5d, cee6bf3b), SVAL(3893b3e6, e012a049), SVAL(e39d8c36, 8506bdaf),
  SVAL(e16a0aa7, 982d6183), SVAL(5a3826bd, fe1de81a), SVAL(ced972b3, bed35fcd),
  SVAL(8e903ee9, 116918a8), SVAL(756befb5, 7b299d56), SVAL(98cb4420, 76a5f6c5),
  SVAL(d310cd35, 0ba6974e), SVAL(d1b647f8, e6380d89), SVAL(b5ea8137, 6f5ae1dd),
  SVAL(cf52ec42, dc76ca61), SVAL(ee2a9fd2, f2f53952), SVAL(02068a04, 8cbb4a4f),
  SVAL(2795a393, 91e5aa61), SVAL(50094e9e, 362288a0), SVAL(557a341d, 1a05658b),
  SVAL(0974456c, 230c81d0), SVAL(e4b28a42, 2c257199), SVAL(8bd702b6, 6b28872c),
  SVAL(b8a8aeb0, 8168eadc), SVAL(231435e7, 032dce9f), SVAL(330005e6, cfcf3824),
  SVAL(ecf49311, 56732afe), SVAL(fa2bed49, 9a7244cd), SVAL(847c40e5, 213a970a),
  SVAL(c685f1a0, b28f5cd8), SVAL(7b097038, 1d22ad26), SVAL(ce00b094, 05b5d608),
  SVAL(a3572534, b519bc02), SVAL(74cbc38f, e7cd0932), SVAL(165c0566, 4f19607e),
  SVAL(a459c365, 1778672b), SVAL(fd38ee3c, 8cf74e30), SVAL(834380f7, 447e23f3),
  SVAL(ec47e111, 98d1f52d), SVAL(43089001, 90fb27a0), SVAL(e0decf74, 00327bc7),
  SVAL(912114f1, 8ede5d9c), SVAL(32848cd9, b3f1e3fa), SVAL(37dbc32b, 9b57118d),
  SVAL(6086ea0a, 1f29cff6), SVAL(b8b022ea, 7985e577), SVAL(b54f7270, d5a7acd4),
  SVAL(26514f0a, 905fd370), SVAL(c6cc93de, 0b040350), SVAL(e531c4a7, f0bccac2),
  SVAL(e7354f4b, 9d73756e), SVAL(5101eb63, ba39250c), SVAL(d62ac371, 46f578aa),
  SVAL(55c023d0, ece39b11)
	},
	{		/* shuffle table */
  SVAL(04635952, eab4809d), SVAL(1e191dc1, e2d8859c), SVAL(f466739b, a78cc47e),
  SVAL(bcb4460e, 4cc9518b), SVAL(bb371472, 5471ebc2), SVAL(13dca6fe, 88234953),
  SVAL(5c92d8e1, 3cd3d726), SVAL(3680546b, 49af9c38), SVAL(0db16bc0, b8a095f8),
  SVAL(7eebfd03, b38af9e6), SVAL(d9bf3100, 0c89b56f), SVAL(9c8b73a7, 143d7ea2),
  SVAL(c486b166, 388f9925), SVAL(c4989f42, ae295fc5), SVAL(6d5578e9, 1dd0107c),
  SVAL(a56f369e, 3b91befa), SVAL(9751ca45, 397d0ee8), SVAL(edc2461a, 688373d7),
  SVAL(d357ea0d, 4934c3c8), SVAL(6437bab1, dcaf0dbc), SVAL(132d70f5, d1676791),
  SVAL(bdbf7ed9, 3e8f804b), SVAL(f22da061, 3e19870b), SVAL(a813fb55, a103e02f),
  SVAL(3063a143, 6c357c03), SVAL(36e17210, 72a5e5bf), SVAL(4f52d0b2, 244f26fa),
  SVAL(ffc8c6e8, a26881eb), SVAL(bc44fe26, 6f2d154f), SVAL(a66945a3, cab1b17b),
  SVAL(2431ffa7, f9a6d522), SVAL(09e7d9c8, e1cf82eb), SVAL(6d0471fb, 73dda812),
  SVAL(80e5d3c7, 72108856), SVAL(cecfc4ca, eafe3c51), SVAL(9256bed4, c3b3c9b0),
  SVAL(3e5826a6, 2674112f), SVAL(bd25eeb0, d169ae1d), SVAL(cd15809d, 2abdf0a3),
  SVAL(c907ba35, 357c1077), SVAL(d7e19227, 1e7843ee), SVAL(12ccb231, 683a3d9c),
  SVAL(9272228b, 66b9cd03), SVAL(105612d6, 300166b0), SVAL(c2659fe8, b8b93dae),
  SVAL(e10ac791, 5abd4030), SVAL(0d347031, b03724a9), SVAL(1f8afbee, 41e2a46d),
  SVAL(4db3ca0b, 727008e0), SVAL(78412641, 654ecdfd), SVAL(34077f49, 5f96bcaf),
  SVAL(d862b34a, 21fe900e), SVAL(708c906d, 48e05f2b), SVAL(2da50dd6, b87027b0),
  SVAL(8c2c1537, 34b0ec0d), SVAL(34c6fa96, 56e9fca0), SVAL(54fa8fd2, 557e6b5b),
  SVAL(43b9444d, cbdbeb78), SVAL(bc7d0cf6, ef31d376), SVAL(777c1298, c39f0111),
  SVAL(ba45eca2, 52d4face), SVAL(80c4d889, 367aac48), SVAL(40682e34, 2b7f1f23),
  SVAL(7ab5ddbc, 2c7e3e0a), SVAL(ffd1d0cb, 259b823c), SVAL(a88ef5ca, f787f1c0),
  SVAL(2ee2327b, d7f14852), SVAL(02ded80c, 5f03aa54), SVAL(81be8df3, 7f930de2),
  SVAL(3a6af986, 488e011f), SVAL(6e76f0d3, 710dcf71), SVAL(6f335c6c, 57f552d6),
  SVAL(008ef84b, d0bdb173), SVAL(65ca0c98, afee90cb), SVAL(748dcd88, 0cb0746c),
  SVAL(d59310de, 8a20a53f), SVAL(9eca466a, 994cc07b), SVAL(ff621092, ee50abb4),
  SVAL(c79ef743, e2e6849c), SVAL(7e176b4e, dea584e3), SVAL(af229851, d7f4b3bc),
  SVAL(835a4ffb, 83e5e3a9), SVAL(d82b7a32, c46711f9), SVAL(2cd18e93, b80d747a),
  SVAL(d40e537a, 8321d92b), SVAL(b05e14df, 2e57c12f), SVAL(3eaed45f, 38b97f8b),
  SVAL(c1ff01cd, c95c136d), SVAL(c49f1815, 3dec73ce), SVAL(8b4cd1c1, da300fc7),
  SVAL(09d2d16d, 8752cac1), SVAL(f89e1348, 79490bfd), SVAL(3deac73a, 07e45a65),
  SVAL(0d7daed1, 563d0fc6), SVAL(43bd97f1, 61fa4e81), SVAL(d7b362f2, 4413c62a),
  SVAL(bb5ba7fc, 5fc22f5c), SVAL(c1545507, 3eab1555), SVAL(1334eae2, 8f051104),
  SVAL(44242ddc, 384c4b90), SVAL(1b75c117, a34b414f), SVAL(7bab6105, 2144f41a),
  SVAL(8ebe585a, 99d7f743), SVAL(4e42c257, 432dba53), SVAL(de0b32da, 153d5ec8),
  SVAL(a8954cd1, 6c47311b), SVAL(adf5c428, ac1f354d), SVAL(0f56d6d7, e22d1fa6),
  SVAL(2d071e69, a6c0d364), SVAL(53cb0c7b, 179770a9), SVAL(b2de65e5, 358f8183),
  SVAL(041d2824, 2d731f17), SVAL(c7139449, 4fc1cf21), SVAL(94a88729, b398e56f),
  SVAL(a44da12c, 7bac758b), SVAL(8e54401c, d5f6d3f9), SVAL(3122ed68, 64d26d77),
  SVAL(7f170293, 64389eae), SVAL(3cb4df89, f5da5177), SVAL(c470e8e0, 6387f60a),
  SVAL(33dbc78c, d1b80187), SVAL(38b503e9, 5f441313), SVAL(fb7ceb54, d84cb651),
  SVAL(bfa9552d, 87776847), SVAL(47e8a857, 9ecb10e5), SVAL(b23488c4, d3081df2),
  SVAL(46e6bf5e, 9c091900), SVAL(bbeaa048, 307fe0cf), SVAL(271e619f, ee99a620),
  SVAL(87c2b86a, 9bb58570), SVAL(19b73eba, c26cf0cf), SVAL(ba400782, 3c9801ca),
  SVAL(7b0d7198, 0f959fce), SVAL(565d4f9e, 7cbe7bdf), SVAL(cc5a2da6, 21d33f36),
  SVAL(8d2dcb2b, ed321284), SVAL(2bef9ccc, f02d14c4), SVAL(86213e5b, 70864746),
  SVAL(3c28656b, 9a3a9420), SVAL(011571e4, 29e2ac8f), SVAL(0429215a, 45ef31d8),
  SVAL(f18d3a44, 6e49010e), SVAL(c61c29f1, f6cf3284), SVAL(8bb2ac5e, 8dae42ef),
  SVAL(1ff558eb, 8dc8f536), SVAL(ae20729a, 02ff404c), SVAL(86f25365, 4f3fdff6),
  SVAL(6f0db4a2, 6cb6c7dc), SVAL(8c94b164, ba75ae74), SVAL(8072777b, 57d49ff8),
  SVAL(9c244bd2, a79bbc34), SVAL(ef376f89, 317a30e3), SVAL(fa0958f0, 9def2868),
  SVAL(0eb1d637, 6751c755), SVAL(03cd8309, bfc3b3d7), SVAL(635e696f, 42165234),
  SVAL(2ddfe9c9, f44d120c), SVAL(d5a517b9, 35e11043), SVAL(0a2d629f, 73ad9b22),
  SVAL(0529947a, 03d704e8), SVAL(3058053c, 07fcb68b), SVAL(c7ad02e3, 6e8c261c),
  SVAL(c996de5a, 1ec52170), SVAL(a8149001, b6567332), SVAL(aa285c19, 9455ec88),
  SVAL(7f38938b, 5762c0b9), SVAL(914af350, 1aa5319b), SVAL(f3033116, 3feee3e5),
  SVAL(1ac9c585, 241f2cb5), SVAL(e0760698, 15e709ab), SVAL(8f69b200, ffd98088),
  SVAL(354c0ec2, aac19f4f), SVAL(70a43cd7, d2819fbc), SVAL(02d1097b, eca983fb),
  SVAL(5023953e, f13638f9), SVAL(53d12078, 5f80f6bd), SVAL(e6d57683, 6243535f),
  SVAL(826f3eba, 278c9647), SVAL(2eb709cf, f42e3023), SVAL(d47d59bc, 5940bf59),
  SVAL(32a70040, 2adcbdea), SVAL(e30b0b31, 43a4d534), SVAL(ab220fd1, 61fa11b2),
  SVAL(2127ba90, 8c88ce88), SVAL(96748ea2, 03074cc5), SVAL(1d84c1c4, 8230a4a6),
  SVAL(1d9e70f1, 7eae53fe), SVAL(a8ed5b62, 03e2b1da), SVAL(2c026757, b29f8c22),
  SVAL(d6879045, 9580da58), SVAL(92575fa5, f109176c), SVAL(5c47a208, f829cb4f),
  SVAL(4dce413e, df126d62), SVAL(05bf43c5, b8ffb590), SVAL(a92a01e5, e0391fc1),
  SVAL(ae517d73, da451e60), SVAL(70c5cdcf, c5abc1c7), SVAL(57671d42, 1174641f),
  SVAL(7eb5dd74, cd9d26d4), SVAL(3abf1e70, b1e821eb), SVAL(8e967932, 18e649f7),
  SVAL(165c0566, 4f19607e), SVAL(a459c365, 1778672b), SVAL(fd38ee3c, 8cf74e30),
  SVAL(834380f7, 447e23f3), SVAL(ec47e111, 98d1f52d), SVAL(43089001, 90fb27a0),
  SVAL(e0decf74, 00327bc7), SVAL(912114f1, 8ede5d9c), SVAL(32848cd9, b3f1e3fa),
  SVAL(37dbc32b, 9b57118d), SVAL(6086ea0a, 1f29cff6), SVAL(b8b022ea, 7985e577),
  SVAL(b54f7270, d5a7acd4), SVAL(26514f0a, 905fd370), SVAL(c6cc93de, 0b040350),
  SVAL(e531c4a7, f0bccac2), SVAL(e7354f4b, 9d73756e), SVAL(5101eb63, ba39250c),
  SVAL(d62ac371, 46f578aa), SVAL(55c023d0, ece39b11), SVAL(23a252f6, 0bae4907),
  SVAL(4f4ad31f, 3818af34), SVAL(689806c4, 03319a17), SVAL(e6354a5d, cee6bf3b),
  SVAL(3893b3e6, e012a049), SVAL(e39d8c36, 8506bdaf), SVAL(e16a0aa7, 982d6183),
  SVAL(5a3826bd, fe1de81a), SVAL(ced972b3, bed35fcd), SVAL(8e903ee9, 116918a8),
  SVAL(756befb5, 7b299d56), SVAL(98cb4420, 76a5f6c5), SVAL(d310cd35, 0ba6974e),
  SVAL(d1b647f8, e6380d89), SVAL(b5ea8137, 6f5ae1dd), SVAL(cf52ec42, dc76ca61),
  SVAL(ee2a9fd2, f2f53952), SVAL(02068a04, 8cbb4a4f), SVAL(2795a393, 91e5aa61),
  SVAL(50094e9e, 362288a0), SVAL(557a341d, 1a05658b), SVAL(0974456c, 230c81d0),
  SVAL(e4b28a42, 2c257199), SVAL(8bd702b6, 6b28872c), SVAL(b8a8aeb0, 8168eadc),
  SVAL(231435e7, 032dce9f), SVAL(330005e6, cfcf3824), SVAL(ecf49311, 56732afe),
  SVAL(fa2bed49, 9a7244cd), SVAL(847c40e5, 213a970a), SVAL(c685f1a0, b28f5cd8),
  SVAL(7b097038, 1d22ad26), SVAL(ce00b094, 05b5d608), SVAL(a3572534, b519bc02),
  SVAL(74cbc38f, e7cd0932)
 	}
};

/*
 * default additive 55 table
 *
 * The additive 55 table in init_a55 has been processed 256 times in order
 * to preload the shuffle table.  The array below is the table before
 * this processing.  These values have came from the Rand Book of Numbers.
 * See " SOURCE OF MAGIC NUMBERS" above.
 *
  * This array is never changed, only copied.
 */
static FULL additive[SCNT] = {
 SVAL(8c20e7e5, 8c4caa12), SVAL(74e36781, 06254c77), SVAL(8220c179, faf7f81d),
 SVAL(b1bf27df, ef95b553), SVAL(a8eaced0, 37c8387d), SVAL(1c78f31a, d6da0de2),
 SVAL(30fbd3f5, 529499ea), SVAL(bec61787, 279b7382), SVAL(f26c9cd7, e907360e),
 SVAL(c7a3b243, 6e54caa9), SVAL(c56bc944, a4fba0b4), SVAL(9a0b31be, 9a3ed149),
 SVAL(64058973, 199388ce), SVAL(d6c04cb7, 3cc1bc11), SVAL(ea18e829, beb6447b),
 SVAL(3e5c3521, ce8fc4e0), SVAL(b4b4c4e9, 0cd2ebaa), SVAL(dd713b28, f6b87567),
 SVAL(18685941, e53d4031), SVAL(1560704f, c6d789a8), SVAL(4a0a3031, 01a25097),
 SVAL(8a6866cd, c974215c), SVAL(1fdac9ac, 989e4aaa), SVAL(d0721d52, 6248e6fa),
 SVAL(91f835dc, 568bdb8a), SVAL(7f830c1a, a1677807), SVAL(3a938494, 51d1596e),
 SVAL(0977ec92, 64dc366f), SVAL(6af1d82e, 505b10d6), SVAL(4019e5c6, 65f9c944),
 SVAL(05848075, f71b024e), SVAL(4eeb5439, 91052276), SVAL(8c7f602b, ca83c3d8),
 SVAL(121b7ebc, 9e34eac6), SVAL(d71faa62, 6f41ddee), SVAL(2a7b7fa7, 9e50c7dc),
 SVAL(609315cf, 9495d6f7), SVAL(96952c31, e10e546b), SVAL(bb564e74, 7cdb7a7f),
 SVAL(58f59523, 6aed4a08), SVAL(390d8131, 5bb0882d), SVAL(f5e6aee4, 527c4e61),
 SVAL(4bcf616f, f771cd8b), SVAL(fdcd00a6, 0a8fdde9), SVAL(73b54ea8, 3ced2fb4),
 SVAL(67c53993, 74a565af), SVAL(883931a9, 08659585), SVAL(5ff183f1, 09ec9509),
 SVAL(a4e93c34, 1c1a0a35), SVAL(cfcfc497, 82e7aef3), SVAL(c5354254, 5097287d),
 SVAL(b2cd1194, 0a50dee0), SVAL(3b776d75, 7a56a0a5), SVAL(e41819e1, 93ad0bde),
 SVAL(33f13c00, 886b99a3)
};


/*
 * current a55 generator state
 */
static RAND a55;


/*
 * default Blum generator state
 *
 * XXX - write
 */
static RANDOM init_blum;


#if 0
/*
 * current Blum generator state
 */
static RANDOM blum;
#endif


/*
 * declare static functions
 */
static void randreseed64 MATH_PROTO((ZVALUE seed, ZVALUE *res));
static int slotcp MATH_PROTO((BITSTR *bitstr, FULL *src, int count));
static void slotcp64 MATH_PROTO((BITSTR *bitstr, FULL *src));



/*
 * Linear Congruential Constants
 *
 * 	a = 6316878969928993981 = 0x57aa0ff473c0ccbd
 *	c = 1363042948800878693 = 0x12ea805718e09865
 *
 * These constants are used in the randreseed64().  See below.
 */
static HALF a_vec[SHALFS] = {SHVAL(57aa, 0ff4, 73c0, ccbd)};
static HALF c_vec[SHALFS] = {SHVAL(12ea, 8057, 18e0, 9865)};
static ZVALUE a_val = {a_vec, SHALFS, 0};
static ZVALUE c_val = {c_vec, SHALFS, 0};


/*
 * randreseed64 - scramble seed in 64 bit chunks
 *
 * given:
 *	a seed
 *
 * returns:
 *	a scrambled seed, or 0 if seed was 0
 *
 * It is 'nice' when a seed of "n" produces a 'significantly different'
 * sequence than a seed of "n+1".  Generators, by convention, assign
 * special significance to the seed of '0'.  It is an unfortunate that
 * people often pick small seed values, particularly when large seed
 * are of significance to the generators found in this file.
 *
 * We will process seed 64 bits at a time until the entire seed has been
 * exhausted.  If a 64 bit chunk is 0, then 0 is returned.  If the 64 bit
 * chunk is non-zero, we will produce a different and unique new scrambled
 * chunk.  In particular, if the seed is 0 we will return 0.  If the seed
 * is non-zero, we will return a different value (though chunks of 64
 * zeros will remain zero).  This scrambling will effectively eliminate
 * the human perceptions that are noted above.
 *
 * It should be noted that the purpose of this process to scramble a seed
 * ONLY.  We do not care if these generators produce good random numbers.
 * We only want to help eliminate the human factors and perceptions
 * noted above.
 *
 * This function scrambles the low 64 bits of a seed, by mapping [0,2^64)
 * into [0,2^64).  This map is one-to-one and onto.  Mapping is performed
 * using  a linear congruence generator of the form:
 *
 *		X1 <-- (a*X0 + c) % m
 *
 * The generator are based on the linear congruential generators found in
 * Knuth's "The Art of Computer Programming - Seminumerical Algorithms",
 * vol 2, 2nd edition (1981), Section 3.6, pages 170-171.
 *
 * Because we process 64 bits we will take:
 *
 *		m = 2^64			(based on note ii)
 *
 * We will scan the Rand book of numbers to look for an 'a' such that:
 *
 *		a mod 8 == 5			(based on note iii)
 *		0.01*m < a < 0.99*m		(based on note iv)
 *		0.01*2^64 < a < 0.99*2^64
 *
 * To help keep the generators independent, we want:
 *
 *		a is prime
 *
 * The choice of an adder 'c' is considered immaterial according (based
 * in note v).  Knuth suggests 'c==1' or 'c==a'.  We elect to select 'c'
 * using the same process as we used to select 'a'.  The choice is
 * 'immaterial' after all, and as long as:
 *
 *		gcd(c, m) == 1		(based on note v)
 *		gcd(c, 2^64) == 1
 *
 * the concerns are met.   It can be shown that if we have:
 *
 *		gcd(a, c) == 1
 *
 * then the adders and multipliers will be more independent.
 *
 * We will obtain the values 'a' and 'c for our generator from the
 * Rand book of numbers.  Because m=2^64 is 20 decimal digits long, we
 * will search the Rand book of numbers 20 at a time.  We will skip any
 * of the 55 values that were used to initialize the additive 55 generators.
 * The values obtained from the Rand book are:
 *
 *		a = 6316878969928993981
 *		c = 1363042948800878693
 *
 * As we stated before, we must map 0 ==> 0.  The linear congruence
 * generator would normally map as follows:
 *
 *	0 ==> 1363042948800878693	(0 ==> c)
 *
 * We can determine which 0<=y<m will produce a given value z by inverting the
 * linear congruence generator:
 *
 *	z = (a*y + c) % m
 *
 *	z = a*y % m + c % m
 *
 *	z-c % m = a*y % m
 *
 *	(z-c % m) * minv(a,m) = (a*y % m) * minv(a,m)
 *		[minv(a,m) is the multiplicitive inverse of a % m]
 *
 *	((z-c % m) * minv(a,m)) % m = ((a*y % m) * minv(a,m)) % m
 *
 *	((z-c % m) * minv(a,m)) % m = y % m
 *		[a % m * minv(a,m) = 1 % m by definition]
 *
 *	((z-c) * minv(a,m)) % m = y % m
 *
 *	((z-c) * minv(a,m)) % m = y
 *		[we defined y to be 0<=y<m]
 *
 * To determine which value maps back into 0, we let z = 0 and compute:
 *
 *	((0-c) * minv(a,m)) % m	==> 10239951819489363767
 *
 * and thus we find that the congruence generator would also normally map:
 *
 *	10239951819489363767 ==> 0
 *
 * To overcome this, and preserve the 1-to-1 and onto map, we force:
 *
 *	0 ==> 0
 *	10239951819489363767 ==> 1363042948800878693
 *
 * To repeat, this function converts a values into a seed value.  With the
 * except of 'seed == 0', every value is mapped into a unique seed value.
 * This mapping need not be complex, random or secure.  All we attempt
 * to do here is to allow humans who pick small or successive seed values
 * to obtain reasonably different sequences from the generators below.
 *
 * NOTE: This is NOT a pseudo random number generator.  This function is
 *	 intended to be used internally by sa55rand() and sshufrand().
 */
static void
randreseed64(seed, res)
	ZVALUE seed;
	ZVALUE *res;
{
	ZVALUE t;		/* temp value */
	ZVALUE chunk;		/* processed 64 bit chunk value */
	ZVALUE seed64;		/* seed mod 2^64 */
	HALF *v64;		/* 64 bit array of HALFs */
	long chunknum;		/* 64 bit chunk number */

	/*
	 * quickly return 0 if seed is 0
	 */
	if (ziszero(seed) || seed.len <= 0) {
		itoz(0, res);
		return;
	}

	/*
	 * allocate result
	 */
	seed.sign = 0;	/* use the value of seed */
	res->len = (int)(((seed.len+SHALFS-1) / SHALFS) * SHALFS);
	res->v = alloc(res->len);
	res->sign = 0;
	memset(res->v, 0, res->len*sizeof(HALF));  /* default value is 0 */

	/*
	 * process 64 bit chunks until done
	 */
	chunknum = 0;
	while (!zislezero(seed)) {

		/*
		 * grab the lower 64 bits of seed
		 */
		if (zge64b(seed)) {
			v64 = alloc(SHALFS);
			memcpy(v64, seed.v, SHALFS*sizeof(HALF));
			seed64.v = v64;
			seed64.len = SHALFS;
			seed64.sign = 0;
		} else {
			zcopy(seed, &seed64);
		}
		zshiftr(seed, SBITS);
		ztrim(&seed);
		ztrim(&seed64);

		/*
		 * do nothing if chunk is zero
		 */
		if (ziszero(seed64)) {
			++chunknum;
			zfree(seed64);
			continue;
		}

		/*
		 * Compute the linear congruence generator map:
		 *
		 *	X1 <-- (a*X0 + c) mod m
		 *
		 * in other words:
		 *
		 *	chunk == (a_val*seed + c_val) mod 2^64
		 */
		zmul(seed64, a_val, &t);
		zfree(seed64);
		zadd(t, c_val, &chunk);
		zfree(t);

		/*
		 * form chunk mod 2^64
		 */
		if (chunk.len > SHALFS) {
			/* result is too large, reduce to 64 bits */
			v64 = alloc(SHALFS);
			memcpy(v64, chunk.v, SHALFS*sizeof(HALF));
			free(chunk.v);
			chunk.v = v64;
			chunk.len = SHALFS;
			ztrim(&chunk);
		}

		/*
		 * Normally, the above equation would map:
		 *
		 *	    f(0) == 1363042948800878693
		 *	    f(10239951819489363767) == 0
		 *
		 * However, we have already forced f(0) == 0.  To preserve the
		 * 1-to-1 and onto map property, we force:
		 *
		 *	    f(10239951819489363767) ==> 1363042948800878693
		 */
		if (ziszero(chunk)) {
			/* load 1363042948800878693 instead of 0 */
			zcopy(c_val, &chunk);
			memcpy(res->v+(chunknum*SHALFS), c_val.v,
			       c_val.len*sizeof(HALF));

		/*
		 * load the 64 bit chunk into the result
		 */
		} else {
			memcpy(res->v+(chunknum*SHALFS), chunk.v,
			       chunk.len*sizeof(HALF));
		}
		++chunknum;
		zfree(chunk);
	}
	ztrim(res);
}


/*
 * zsrand - seed the a55 generator
 *
 * given:
 *	pseed    - ptr to seed of the generator or NULL
 *	pmat55  - additive 55 state table or NULL
 *
 * returns:
 *	previous a55 state
 */
RAND *
zsrand(pseed, pmat55)
	ZVALUE *pseed;
	MATRIX *pmat55;
{
	RAND *ret;		/* previous a55 state */
	VALUE *v;		/* value from a passed matrix */
	ZVALUE zscram;		/* scrambled 64 bit seed */
	FULL shufxor[SLEN];	/* zshufxor as an 64 bit array of FULLs */
	long indx;		/* index to shuffle slots for seeding */
	int i;

	/*
	 * firewall
	 */
	if (pseed != NULL && zisneg(*pseed)) {
		math_error("neg seeds for srand reserved for future use");
	}

	/*
	 * initialize state if first call
	 */
	if (!a55.seeded) {
		a55 = init_a55;
	}

	/*
	 * save the current state to return later
	 */
	ret = (RAND *)malloc(sizeof(RAND));
	if (ret == NULL) {
		math_error("cannot allocate RAND state");
	}
	*ret = a55;

	/*
	 * if call was srand(), just return current state
	 */
	if (pseed == NULL && pmat55 == NULL) {
		return ret;
	}

	/*
	 * if call is srand(0), initialize and return quickly
	 */
	if (pmat55 == NULL && ziszero(*pseed)) {
		a55 = init_a55;
		return ret;
	}

	/*
	 * clear buffered bits, initialize pointers
	 */
	a55.seeded = 0;	/* not seeded now */
	a55.j = INIT_J-1;
	a55.k = INIT_K-1;
	a55.bits = 0;
	memset(a55.buffer, 0, sizeof(a55.buffer));

	/*
	 * load additive table
	 *
	 * We will load the default additive table unless we are passed a
	 * matrix.  If we are passed a matrix, we will load the first 55
	 * values mod 2^64 instead.
	 */
	if (pmat55 == NULL) {
		memcpy(a55.slot, additive, sizeof(additive));
	} else {

		/*
		 * use the first 55 entries from the matrix arg
		 */
		if (pmat55->m_size < A55) {
			math_error("matrix for srand has < 55 elements");
		}
		for (v=pmat55->m_table, i=0; i < A55; ++i, ++v) {

			/* reject if not integer */
			if (v->v_type != V_NUM || qisfrac(v->v_num)) {
			    math_error("matrix for srand must contain ints");
			}

			/* load table element from matrix element mod 2^64 */
			SLOAD(a55, i, v->v_num->num);
		}
	}

	/*
	 * scramble the seed in 64 bit chunks
	 */
	if (pseed != NULL) {
		randreseed64(*pseed, &zscram);
	}

	/*
	 * xor additive table with the rehashed lower 64 bits of seed
	 */
	if (pseed != NULL && !ziszero(zscram)) {

		/* xor additive table with lower 64 bits of seed */
		SMOD64(shufxor, zscram);
		for (i=0; i < A55; ++i) {
			SXOR(a55, i, shufxor);
		}
	}

	/*
	 * shuffle additive 55 table according to seed, if passed
	 */
        if (pseed != NULL && zge64b(zscram)) {

        	/* prepare the seed for additive slot shuffeling */
        	zshiftr(zscram, 64);
		ztrim(&zscram);

        	/* shuffle additive table */
        	for (i=A55-1; i > 0 && !zislezero(zscram); --i) {

        		/* determine what we will swap with */
        		indx = zdivi(zscram, i+1, &zscram);

        		/* do nothing if swap with itself */
        		if (indx == i) {
        			continue;
        		}

        		/* swap slot[i] with slot[indx] */
        		SSWAP(a55, i, indx);
        	}
        	zfree(zscram);
        }

	/*
	 * load the shuffle table
	 *
	 * We will generate SHUFCNT entries from the additive 55 slots
	 * and fill the shuffle table in consequtive order.
	 */
	for (i=0; i < SHUFCNT; ++i) {

		/* bump j and k */
		if (++a55.j >= A55) {
			a55.j = 0;
		}
		if (++a55.k >= A55) {
			a55.k = 0;
		}

		/* slot[k] += slot[j] */
		SADD(a55, a55.k, a55.j);

		/* shuf[i] = slot[k] */
		SSHUF(a55, i, a55.k);
	}

	/*
	 * note that we are seeded
	 */
	a55.seeded = 1;

	/*
	 * return the previous state
	 */
	return ret;
}


/*
 * zsetrand - set the a55 generator state
 *
 * given:
 *	state - the state to copy
 *
 * returns:
 *	previous a55 state
 */
RAND *
zsetrand(state)
	RAND *state;
{
	RAND *ret;		/* previous a55 state */

	/*
	 * initialize state if first call
	 */
	if (!a55.seeded) {
		a55 = init_a55;
	}

	/*
	 * save the current state to return later
	 */
	ret = (RAND *)malloc(sizeof(RAND));
	if (ret == NULL) {
		math_error("cannot allocate RAND state");
	}
	*ret = a55;

	/*
	 * load the new state
	 */
	a55 = *state;

	/*
	 * return the previous state
	 */
	return ret;
}


/*
 * slotcp - copy up to 64 bits from a 64 bit array of FULLs to some HALFs
 *
 * We will copy data from an array of FULLs into an array of HALFs.
 * The destination within the HALFs is some bit location found in bitstr.
 * We will attempt to copy 64 bits, but if there is not enough room
 * (bits not yet loaded) in the destination bit string we will transfer
 * what we can.
 *
 * The src slot is 64 bits long and is stored as an array of FULLs.
 * When FULL_BITS is 64 the element is 1 FULL, otherwise FULL_BITS
 * is 32 bits and the element is 2 FULLs.  The most significant bit
 * in the array (highest bit in the last FULL of the array) is to
 * be transfered to the most significant bit in the desitnation.
 *
 * given:
 *	bitstr	- most significant destination bit in a bit string
 *	src     - low order FULL in a 64 bit slot
 *	count	- number of bits to trnsfer (must be 0 < count <= 64)
 *
 * returns:
 *	number of bits transfered
 */
static int
slotcp(bitstr, src, count)
	BITSTR *bitstr;
	FULL *src;
	int count;
{
	HALF *dh;		/* most sigificant HALF in dest */
	int dnxtbit;		/* next bit beyond most signif in dh */
	int need;		/* number of bits we need to transfer */
	int ret;		/* bits transfered */

	/*
	 * determine how many bits we actually need to transfer
	 */
	dh = bitstr->loc;
	dnxtbit = bitstr->bit+1;
	count &= (SBITS-1);
	need = (bitstr->len < count) ? bitstr->len : count;

	/*
	 * prepare for the return
	 *
	 * Note the final bitstr location after we have moved the
	 * position down 'need' bits.
	 */
	bitstr->len -= need;
	bitstr->loc -= need / BASEB;
	bitstr->bit -= need % BASEB;
	if (bitstr->bit < 0) {
		--bitstr->loc;
		bitstr->bit += BASEB;
	}
	ret = need;

	/*
	 * deal with aligned copies quickly
	 */
	if (dnxtbit == BASEB) {
		if (need == SBITS) {
#if 2*FULL_BITS == SBITS
			*dh-- = (HALF)(src[SLEN-1] >> BASEB);
			*dh-- = (HALF)(src[SLEN-1]);
#endif
			*dh-- = (HALF)(src[0] >> BASEB);
			*dh = (HALF)(src[0]);
#if 2*FULL_BITS == SBITS
		} else if (need > FULL_BITS+BASEB) {
			*dh-- = (HALF)(src[SLEN-1] >> BASEB);
			*dh-- = (HALF)(src[SLEN-1]);
			*dh-- = (HALF)(src[0] >> BASEB);
			*dh = ((HALF)src[0] &
				     highhalf[need-FULL_BITS-BASEB]);
		} else if (need > FULL_BITS) {
			*dh-- = (HALF)(src[SLEN-1] >> BASEB);
			*dh-- = (HALF)(src[SLEN-1]);
			*dh = ((HALF)(src[0] >> BASEB) &
				     highhalf[need-FULL_BITS]);
#endif
		} else if (need > BASEB) {
			*dh-- = (HALF)(src[SLEN-1] >> BASEB);
			*dh = ((HALF)(src[SLEN-1]) & highhalf[need-BASEB]);
		} else {
			*dh = ((HALF)(src[SLEN-1] >> BASEB) & highhalf[need]);
		}
		return ret;
	}

	/*
	 * load the most significant HALF
	 */
	if (need >= dnxtbit) {
		/* fill up the most significant HALF */
		*dh-- |= (HALF)(src[SLEN-1] >> (FULL_BITS-dnxtbit));
		need -= dnxtbit;
	} else if (need > 0) {
		/* we exhaust our need before 1st half is filled */
		*dh |= (HALF)((src[SLEN-1] >> (FULL_BITS-need)) <<
				(dnxtbit-need));
		return ret;	/* our need has been filled */
	} else {
		return ret;	/* our need has been filled */
	}

	/*
	 * load the 2nd most significant HALF
	 */
	if (need > BASEB) {
		/* fill  up the 2nd most significant HALF */
		*dh-- = (HALF)(src[SLEN-1] >> (BASEB-dnxtbit));
		need -= BASEB;
	} else if (need > 0) {
		/* we exhaust our need before 2nd half is filled */
		*dh |= ((HALF)(src[SLEN-1] >> (BASEB-dnxtbit)) &
			 highhalf[need]);
		return ret;	/* our need has been filled */
	} else {
		return ret;	/* our need has been filled */
	}

	/*
	 * load the 3rd most significant HALF
	 *
	 * At this point we know that our 3rd HALF will force us
	 * to cross into a second FULL for systems with 32 bit FULLs.
	 * We know this because the aligned case has been previously
	 * taken care of above.
	 *
	 * For systems that have 64 bit FULLs (and 32 bit HALFs) this
	 * is will be our least significant HALF.  We also know that
	 * the need must be < BASEB.
	 */
#if FULL_BITS == SBITS
	*dh |= (((HALF)src[0] & highhalf[dnxtbit+need]) << dnxtbit);
#else
	if (need > BASEB) {
		/* load the remaining bits from the most signif FULL */
		*dh-- = ((((HALF)src[SLEN-1] & lowhalf[BASEB-dnxtbit])
			   << dnxtbit) | (HALF)(src[0] >> (FULL_BITS-dnxtbit)));
		need -= BASEB;
	} else if (need > 0) {
		/* load the remaining bits from the most signif FULL */
		*dh-- |= (((((HALF)src[SLEN-1] & lowhalf[BASEB-dnxtbit])
			 << dnxtbit) | (HALF)(src[0] >> (FULL_BITS-dnxtbit))) &
			  highhalf[need]);
		return ret;	/* our need has been filled */
	} else {
		return ret;	/* our need has been filled */
	}

	/*
	 * load the 4th most significant HALF
	 *
	 * At this point, only 32 bit FULLs are operating.
	 */
	if (need > BASEB) {
		/* fill  up the 2nd most significant HALF */
		*dh-- = (HALF)(src[0] >> (BASEB-dnxtbit));
		/* no need todo: need -= BASEB, because we are nearly done */
	} else if (need > 0) {
		/* we exhaust our need before 2nd half is filled */
		*dh |= ((HALF)(src[0] >> (BASEB-dnxtbit)) &
			 highhalf[need]);
		return ret;	/* our need has been filled */
	} else {
		return ret;	/* our need has been filled */
	}

	/*
	 * load the 5th and least sigicant HALF
	 *
	 * At this point we know that the need will be satisfied.
	 */
	*dh |= (((HALF)src[0] & lowhalf[BASEB-dnxtbit]) << dnxtbit);
#endif
	return ret;	/* our need has been filled */
}


/*
 * slotcp64 - copy 64 bits from a 64 bit array of FULLs to some HALFs
 *
 * We will copy data from an array of FULLs into an array of HALFs.
 * The destination within the HALFs is some bit location found in bitstr.
 * Unlike slotcp(), this function will always copy 64 bits.
 *
 * The src slot is 64 bits long and is stored as an array of FULLs.
 * When FULL_BITS is 64 this array is 1 FULL, otherwise FULL_BITS
 * is 32 bits and the array is 2 FULLs.  The most significant bit
 * in the array (highest bit in the last FULL of the array) is to
 * be transfered to the most significant bit in the desitnation.
 *
 * given:
 *	bitstr	- most significant destination bit in a bit string
 *	src     - low order FULL in a 64 bit slot
 *
 * returns:
 *	number of bits transfered
 */
static void
slotcp64(bitstr, src)
	BITSTR *bitstr;
	FULL *src;
{
	HALF *dh = bitstr->loc;		/* most sigificant HALF in dest */
	int dnxtbit = bitstr->bit+1;	/* next bit beyond most signif in dh */

	/*
	 * prepare for the return
	 *
	 * Sinc we are moving the point 64 bits down, we know that
	 * the bit location (bitstr->bit) will remain the same.
	 */
	bitstr->len -= SBITS;
	bitstr->loc -= SBITS/BASEB;

	/*
	 * deal with aligned copies quickly
	 */
	if (dnxtbit == BASEB) {
#if 2*FULL_BITS == SBITS
		*dh-- = (HALF)(src[SLEN-1] >> BASEB);
		*dh-- = (HALF)(src[SLEN-1]);
#endif
		*dh-- = (HALF)(src[0] >> BASEB);
		*dh = (HALF)(src[0]);
		return;
	}

	/*
	 * load the most significant HALF
	 */
	*dh-- |= (HALF)(src[SLEN-1] >> (FULL_BITS-dnxtbit));

	/*
	 * load the 2nd most significant HALF
	 */
	*dh-- = (HALF)(src[SLEN-1] >> (BASEB-dnxtbit));

	/*
	 * load the 3rd most significant HALF
	 *
	 * At this point we know that our 3rd HALF will force us
	 * to cross into a second FULL for systems with 32 bit FULLs.
	 * We know this because the aligned case has been previously
	 * taken care of above.
	 *
	 * For systems that have 64 bit FULLs (and 32 bit HALFs) this
	 * is will be our least significant HALF.
	 */
#if FULL_BITS == SBITS
	*dh |= (((HALF)src[0] & lowhalf[BASEB-dnxtbit]) << dnxtbit);
#else
	/* load the remaining bits from the most signif FULL */
	*dh-- = ((((HALF)src[SLEN-1] & lowhalf[BASEB-dnxtbit])
		   << dnxtbit) | (HALF)(src[0] >> (FULL_BITS-dnxtbit)));

	/*
	 * load the 4th most significant HALF
	 *
	 * At this point, only 32 bit FULLs are operating.
	 */
	*dh-- = (HALF)(src[0] >> (BASEB-dnxtbit));

	/*
	 * load the 5th and least sigicant HALF
	 *
	 * At this point we know that the need will be satisfied.
	 */
	*dh |= (((HALF)src[0] & lowhalf[BASEB-dnxtbit]) << dnxtbit);
#endif
}


/*
 * zrandskip - skip s bits
 *
 * given:
 *	count - number of bits to be skipped
 */
void
zrandskip(cnt)
	long cnt;
{
	int indx;		/* shuffle entry index */

	/*
	 * initialize state if first call
	 */
	if (!a55.seeded) {
		a55 = init_a55;
	}

	/*
	 * skip required bits in the buffer
	 */
	if (a55.bits > 0 && a55.bits <= cnt) {

		/* just toss the buffer bits */
		cnt -= a55.bits;
		a55.bits = 0;
		memset(a55.buffer, 0, sizeof(a55.buffer));

	} else if (a55.bits > 0 && a55.bits > cnt) {

		/* buffer contains more bits than we need to toss */
#if FULL_BITS == SBITS
		a55.buffer[0] <<= cnt;
#else
		if (cnt >= FULL_BITS) {
			a55.buffer[SLEN-1] = (a55.buffer[0] << cnt);
			a55.buffer[0] = 0;
		} else {
			a55.buffer[SLEN-1] =
			    ((a55.buffer[SLEN-1] << cnt) |
			     (a55.buffer[0] >> (FULL_BITS-cnt)));
			a55.buffer[0] <<= cnt;
		}
#endif
		return;	/* skip need satisfied */
	}

	/*
	 * skip 64 bits at a time
	 */
	while (cnt >= SBITS) {

		/* bump j and k */
		if (++a55.j >= A55) {
			a55.j = 0;
		}
		if (++a55.k >= A55) {
			a55.k = 0;
		}

		/* slot[k] += slot[j] */
		SADD(a55, a55.k, a55.j);

		/* we will ignore the output value of a55.slot[indx] */
		indx = SINDX(a55, a55.k);
		cnt -= SBITS;

		/* store a55.k into a55.slot[indx] */
		SSHUF(a55, indx, a55.k);
	}

	/*
	 * skip the final bits
	 */
	if (cnt > 0) {

		/* bump j and k */
		if (++a55.j >= A55) {
			a55.j = 0;
		}
		if (++a55.k >= A55) {
			a55.k = 0;
		}

		/* slot[k] += slot[j] */
		SADD(a55, a55.k, a55.j);

		/* we will ignore the output value of a55.slot[indx] */
		indx = SINDX(a55, a55.k);

		/*
		 * We know the buffer is empty, so fill it
		 * with any unused bits.  Copy SBITS-trans bits
		 * from slot[indx] into buffer.
		 */
		a55.bits = (int)(SBITS-cnt);
		memcpy(a55.buffer, &a55.shuf[indx*SLEN],
		       sizeof(a55.buffer));

		/*
		 * shift the buffer bits all the way up to
		 * the most significant bit
		 */
#if FULL_BITS == SBITS
		a55.buffer[0] <<= cnt;
#else
		if (cnt >= FULL_BITS) {
			a55.buffer[SLEN-1] = (a55.buffer[0] << cnt);
			a55.buffer[0] = 0;
		} else {
			a55.buffer[SLEN-1] =
			    ((a55.buffer[SLEN-1] << cnt) |
			     (a55.buffer[0] >> (FULL_BITS-cnt)));
			a55.buffer[0] <<= cnt;
		}
#endif

		/* store a55.k into a55.slot[indx] */
		SSHUF(a55, indx, a55.k);
	}
}


/*
 * zrand - crank the a55 generator for some bits
 *
 * given:
 *	count - number of bits required
 *	res - where to place the random bits as ZVALUE
 */
void
zrand(cnt, res)
	long cnt;
	ZVALUE *res;
{
	long hlen;		/* length of ZVALUE in HALFs */
	BITSTR dest;		/* destination bit string */
	int trans;		/* bits transfered */
	int indx;		/* shuffle entry index */

	/*
	 * firewall
	 */
	if (cnt <= 0) {
		if (cnt == 0) {
			/* zero length random number is always 0 */
			itoz(0, res);
			return;
		} else {
			math_error("negative zrand bit count");
		}
#if LONG_BITS > 32
	} else if (cnt > (1L<<31)) {
		math_error("huge rand bit count in internal zrand function");
#endif
	}

	/*
	 * initialize state if first call
	 */
	if (!a55.seeded) {
		a55 = init_a55;
	}

	/*
	 * allocate storage
	 */
	hlen = (cnt+BASEB-1)/BASEB;
	res->len = (LEN)hlen;
	res->v = alloc((LEN)hlen);
	memset(res->v, 0, hlen*sizeof(HALF));

	/*
	 * dest bit string
	 */
	dest.len = (int)cnt;
	dest.loc = res->v + (hlen-1);
	dest.bit = (int)((cnt-1) % BASEB);

	/*
	 * load from buffer first
	 */
	if (a55.bits > 0) {

		/*
		 * We know there are only a55.bits in the buffer, so
		 * transfer as much as we can (treating it as a slot)
		 * and return the bit transfer count.
		 */
		trans = slotcp(&dest, a55.buffer, a55.bits);

		/*
		 * If we need to keep bits in the buffer,
		 * shift the buffer bits all the way up to
		 * the most significant unused bit.
		 */
		if (trans < a55.bits) {
#if FULL_BITS == SBITS
			a55.buffer[0] <<= trans;
#else
			if (trans >= FULL_BITS) {
				a55.buffer[SLEN-1] =
				    (a55.buffer[0] << (trans-FULL_BITS));
				a55.buffer[0] = 0;
			} else {
				a55.buffer[SLEN-1] =
				    ((a55.buffer[SLEN-1] << trans) |
				     (a55.buffer[0] >> (FULL_BITS-trans)));
				a55.buffer[0] <<= trans;
			}
#endif
		}
		/* note that we have fewer bits in the buffer */
		a55.bits -= trans;
	}

	/*
	 * spin the generator until we need less than 64 bits
	 *
	 * The buffer did not contain enough bits, so we crank the
	 * a55 generator and load then 64 bits at a time.
	 */
	while (dest.len >= SBITS) {

		/* bump j and k */
		if (++a55.j >= A55) {
			a55.j = 0;
		}
		if (++a55.k >= A55) {
			a55.k = 0;
		}

		/* slot[k] += slot[j] */
		SADD(a55, a55.k, a55.j);

		/* select slot index to output */
		indx = SINDX(a55, a55.k);

		/* move up to 64 bits from slot[indx] to dest */
		slotcp64(&dest, &a55.shuf[indx*SLEN]);

		/* store a55.k into a55.slot[indx] */
		SSHUF(a55, indx, a55.k);
	}

	/*
	 * spin the generator one last time to fill out the remaining need
	 */
	if (dest.len > 0) {

		/* bump j and k */
		if (++a55.j >= A55) {
			a55.j = 0;
		}
		if (++a55.k >= A55) {
			a55.k = 0;
		}

		/* slot[k] += slot[j] */
		SADD(a55, a55.k, a55.j);

		/* select slot index to output */
		indx = SINDX(a55, a55.k);

		/* move up to 64 bits from slot[indx] to dest */
		trans = slotcp(&dest, &a55.shuf[indx*SLEN], dest.len);

		/* buffer up unused bits if we are done */
		if (trans != SBITS) {

			/*
			 * We know the buffer is empty, so fill it
			 * with any unused bits.  Copy SBITS-trans bits
			 * from slot[indx] into buffer.
			 */
			a55.bits = SBITS-trans;
			memcpy(a55.buffer, &a55.shuf[indx*SLEN],
			       sizeof(a55.buffer));

			/*
			 * shift the buffer bits all the way up to
			 * the most significant bit
			 */
#if FULL_BITS == SBITS
			a55.buffer[0] <<= trans;
#else
			if (trans >= FULL_BITS) {
				a55.buffer[SLEN-1] =
				    (a55.buffer[0] << (trans-FULL_BITS));
				a55.buffer[0] = 0;
			} else {
				a55.buffer[SLEN-1] =
				    ((a55.buffer[SLEN-1] << trans) |
				     (a55.buffer[0] >> (FULL_BITS-trans)));
				a55.buffer[0] <<= trans;
			}
#endif
		}

		/* store a55.k into a55.slot[indx] */
		SSHUF(a55, indx, a55.k);
	}
	res->sign = 0;
	ztrim(res);
}


/*
 * zrandrange - generate a random value in the range [low, high)
 *
 * given:
 *	low - low value of range
 *	high - beyond end of range
 *	res - where to place the random bits as ZVALUE
 */
void
zrandrange(low, high, res)
	ZVALUE low;
	ZVALUE high;
	ZVALUE *res;
{
	ZVALUE range;		/* high-low */
	ZVALUE rval;		/* random value [0, 2^bitlen) */
	ZVALUE rangem1;		/* range - 1 */
	long bitlen;		/* smallest power of 2 >= diff */

	/*
	 * firewall
	 */
	if (zrel(low, high) >= 0) {
		math_error("srand low range >= high range");
	}

	/*
	 * determine the size of the random number needed
	 */
	zsub(high, low, &range);
	if (zisone(range)) {
		zfree(range);
		*res = low;
		return;
	}
	zsub(range, _one_, &rangem1);
	bitlen = 1+zhighbit(rangem1);
	zfree(rangem1);

	/*
	 * generate a random value between [0, diff)
	 *
	 * We will not fall into the trap of thinking that we can simply take
	 * a value mod 'range'.  Consider the case where 'range' is '80'
	 * and we are given pseudo-random numbers [0,100).  If we took them
	 * mod 80, then the numbers [0,20) would be produced more frequently
	 * because the numbers [81,100) mod 80 wrap back into [0,20).
	 */
	rval.v = NULL;
	do {
		if (rval.v != NULL) {
			zfree(rval);
		}
		zrand(bitlen, &rval);
	} while (zrel(rval, range) >= 0);

	/*
	 * add in low value to produce the range [0+low, diff+low)
	 * which is the range [low, high)
	 */
	zadd(rval, low, res);
	zfree(rval);
	zfree(range);
}


/*
 * irand - generate a random long in the range [0, s)
 *
 * given:
 *	s - limit of the range
 *
 * returns:
 *	random long in the range [0, s)
 */
long
irand(s)
	long s;
{
	ZVALUE z1, z2;
	long res;

	if (s <= 0)
		math_error("Non-positive argument for irand()");
	if (s == 1)
		return 0;
	itoz(s, &z1);
	zrandrange(_zero_, z1, &z2);
	res = ztoi(z2);
	zfree(z1);
	zfree(z2);
	return res;
}


/*
 * randcopy - make a copy of an a55 state
 *
 * given:
 *	state - the state to copy
 *
 * returns:
 *	a malloced copy of the state
 */
RAND *
randcopy(state)
	RAND *state;
{
	RAND *ret;	/* return copy of state */

	/*
	 * malloc state
	 */
	ret = (RAND *)malloc(sizeof(RAND));
	if (ret == NULL) {
		math_error("can't allocate RAND state");
	}
	*ret = *state;

	/*
	 * return copy
	 */
	return ret;
}


/*
 * randomcopy - make a copy of a Blum state
 *
 * given:
 *	state - the state to copy
 *
 * returns:
 *	a malloced copy of the state
 */
RANDOM *
randomcopy(state)
	RANDOM *state;
{
	RANDOM *ret;	/* return copy of state */

	/*
	 * malloc state
	 */
	ret = (RANDOM *)malloc(sizeof(RANDOM));
	if (ret == NULL) {
		math_error("can't allocate RANDOM state");
	}

	/*
	 * clone data
	 */
	ret->seeded = state->seeded;
	ret->bits = state->bits;
	memcpy(ret->buffer, state->buffer, sizeof(state->buffer));
	if (state->r.v == NULL) {
		ret->r.v = NULL;
	} else {
		zcopy(state->r, &ret->r);
	}
	if (state->n.v == NULL) {
		ret->n.v = NULL;
	} else {
		zcopy(state->n, &ret->n);
	}

	/*
	 * return copy
	 */
	return ret;
}


/*
 * randfree - free an a55 state
 *
 * given:
 *	state - the state to free
 */
void
randfree(state)
	RAND *state;
{
	/* free it */
	free(state);
}


/*
 * randomfree - free a Blum state
 *
 * given:
 *	state - the state to free
 */
void
randomfree(state)
	RANDOM *state;
{
	/* free it */
	free(state);
}


/*
 * randcmp - compare two a55 states
 *
 * given:
 *	s1 - first state to compate
 *	s2 - second state to compate
 *
 * return:
 *	TRUE if states differ
 */
BOOL
randcmp(s1, s2)
	RAND *s1;
	RAND *s2;
{
	/*
	 * assume uninitialized state == the default seeded state
	 */
	if (!s1->seeded) {
		if (!s2->seeded) {
			/* uninitialized == uninitialized */
			return TRUE;
		} else {
			/* uninitialized only equals default state */
			return randcmp(s2, &init_a55);
		}
	} else if (!s2->seeded) {
		if (!s1->seeded) {
			/* uninitialized == uninitialized */
			return TRUE;
		} else {
			/* uninitialized only equals default state */
			return randcmp(s1, &init_a55);
		}
	}

	/* compare states */
	return (BOOL)(memcmp(s1, s2, sizeof(RAND)) != 0);
}


/*
 * randomcmp - compare two Blum states
 *
 * given:
 *	s1 - first state to compate
 *	s2 - second state to compate
 *
 * return:
 *	TRUE if states are the same
 */
BOOL
randomcmp(s1, s2)
	RANDOM *s1;
	RANDOM *s2;
{
	/*
	 * assume uninitialized state == the default seeded state
	 */
	if (!s1->seeded) {
		if (!s2->seeded) {
			/* uninitialized == uninitialized */
			return TRUE;
		} else {
			/* uninitialized only equals default state */
			return randomcmp(s2, &init_blum);
		}
	} else if (!s2->seeded) {
		if (!s1->seeded) {
			/* uninitialized == uninitialized */
			return TRUE;
		} else {
			/* uninitialized only equals default state */
			return randomcmp(s1, &init_blum);
		}
	}

	/*
	 * compare bit buffer
	 */
	if (s1->bits != s2->bits ||
	    memcmp(s1->buffer, s2->buffer, sizeof(s1->buffer)) != 0) {
		return FALSE;
	}

	/*
	 * compare quadratic residues
	 */
	if (!zcmp(s1->r, s2->r)) {
		return FALSE;
	}

	/*
	 * compare modului
	 */
	if (!zcmp(s1->n, s2->n)) {
		return FALSE;
	}

	/*
	 * they are equal
	 */
	return TRUE;
}


/*
 * randprint - print an a55 state
 *
 * given:
 *	state - state to print
 *	flags - print flags passed from printvalue() in value.c
 */
/*ARGSUSED*/
void
randprint(state, flags)
	RAND *state;
	int flags;
{
	math_str("RAND state");
}


/*
 * randomprint - print a Blum state
 *
 * given:
 *	state - state to print
 *	flags - print flags passed from printvalue() in value.c
 */
/*ARGSUSED*/
void
randomprint(state, flags)
	RANDOM *state;
	int flags;
{
	math_str("RANDOM state");
}
