/*
 *	random.h
 *
 *	Copyright (c) 1993-1995 by DataBeam Corporation, Lexington, KY
 *
 *	Abstract:
 *		This is the interface file for the RandomNumberGenerator class.
 *		Instances of this class can generate random numbers within a specifed
 *		range on demand.  Many of these objects can exist at once, and they
 *		will not interfere with each other.
 *                  
 *	Caveats:
 *		None.
 *
 *	Author:
 *		James J. Johnstone IV
 */
#ifndef _RANDOM_
#define _RANDOM_

/*
 *	The data type of the return value of the RandomNumberGenerator class.
 */

typedef	ULong				RandomValue;

#ifdef USE_RANDOM_CLASS

/*
 *	This typedef is an enumeration of all possible random number generation
 *	algorithms and is used when constructing a new random number generator.
 *	See "Numerical Recipes in 'C'" for details as to the difference between
 *	the various algorithms.
 */
typedef	enum
{
	ALGORITHM_RAN1,
	ALGORITHM_RANQD2,
	ALGORITHM_RAN4
} Algorithm;
typedef	Algorithm * 		PAlgorithm;

/*
 *	The default algorithm for the random number generator object.
 */
#define DEFAULT_ALGORITHM	ALGORITHM_RAN1

/*
 *	If specified as the seed value, a random seed will be generated by the 
 *	random number generator.
 */
#define RANDOM_SEED			0

/*
 *	Defines for ran1() algorithm from "Numerical Recipes in 'C'"
 */
#define IA					16807
#define	IM					2147483647L
#define	AM					(1.0/IM)
#define IQ					127773L
#define IR					2836
#define	NTAB				32
#define	NDIV				(1+(IM-1)/NTAB)
#define	EPS					1.2e-7
#define	RNMX				(1.0-EPS)

/*
 *	Defines for ranqd2() algorithm from "Numerical Recipes in 'C'"
 */
#define RANQD2_A			1664525L
#define RANQD2_C			1013904223L

/*
 *	Defines for ranqd2() and ran4() algorithms from "Numerical Recipes in 'C'"
 */
#define	JFLONE				0x3f800000L
#define JFLMSK				0x007fffffL

/*
 *	Defines for the ran4() algorithm from "Numerical Recipes in 'C'"
 */
#define NITER				4

/*
 *	The definition of the RandomNumberGenerator class.
 */
class RandomNumberGenerator
{
	public:
						RandomNumberGenerator ();
						RandomNumberGenerator (
								ULong			seed);
						RandomNumberGenerator (
								Algorithm		algorithm);
						RandomNumberGenerator (
								Algorithm		algorithm,
								ULong			seed);
		virtual			~RandomNumberGenerator ();
		RandomValue		GetRandomNumber (
								RandomValue		lo_extent,
								RandomValue		hi_extent);
		Void			Reseed ();
		Void			Reseed (
								ULong			seed);

	private:
		Void			GenerateSeed (
								ULong			seed);
		Float			RAN1UniformDeviate ();
		Float			RAN4UniformDeviate ();
		Void 			PseudoDESHashing (
								ULong 			*lword, 
								ULong 			*irword);

		Algorithm		Algorithm_In_Use;
		Long			Running_Random_Number;
};		
typedef RandomNumberGenerator *		PRandomNumberGenerator;

/*
 *	RandomNumberGenerator ()
 *
 *	Functional Description:
 *		This version of the constructor is used to create a random number
 *		generator object that has been automatically seeded with the current
 *		time.  The default algorithm will be used.
 *
 *	Formal Parameters:
 *		None.
 *
 *	Return Value:
 *		None.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

/*
 *	RandomNumberGenerator (
 *			ULong	seed)
 *
 *	Functional Description:
 *		This version of the constructor is used to create a random number
 *		generator object which is seeded with the supplied value.  The default
 *		algorithm will be used.
 *
 *	Formal Parameters:
 *		seed (i)
 *			A value used to seed the random number generator.  If the seed value
 *			is zero, the random number generator object will use a random seed
 *			value based on the time. 
 *
 *	Return Value:
 *		None.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

/*
 *	RandomNumberGenerator (
 *			Algorithm		algorithm)
 *
 *	Functional Description:
 *		This version of the constructor is used to create a random number
 *		generator object that has been automatically seeded with the current
 *		time.  The algorithm specifies the algorithm to be used.
 *
 *	Formal Parameters:
 *		algorithm (i)
 *			The random number generation algorithm to be used.  The parameter
 *			algorithm must be one of the following:
 *	
 *			ALGORITHM_RAN1
 *				A good general purpose algorithm with a rather long period.
 *				This algorithm was benchmarked on a Gateway 2000 486/33C at
 *				29+ Kops (thousand operations per second).
 *			ALGORITHM_RANQD2
 *				A quick and dirty algorithm.  Use this algorithm if speed is an
 *				issue and the period of the random sequence is unimportant.
 *				This algorithm was benchmarked on a Gateway 2000 486/33C at
 *				49+ Kops (thousand operations per second).
 *			ALGORITHM_RAN4
 *				A slow algorithm with an exceptionally long period.
 *				This algorithm was benchmarked on a Gateway 2000 486/33C at
 *				18+ Kops (thousand operations per second).
 *
 *	Return Value:
 *		None.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

/*
 *	RandomNumberGenerator (
 *			Algorithm		algorithm,
 *			ULong			seed)
 *
 *	Functional Description:
 *		This version of the constructor is used to create a random number
 *		generator object which is seeded with the supplied value.  The algorithm
 *		specified the algorithm to be used.
 *
 *	Formal Parameters:
 *		algorithm (i)
 *			The random number generation algorithm to be used.  The parameter
 *			algorithm must be one of the following:
 *	
 *			ALGORITHM_RAN1
 *				A good general purpose algorithm with a rather long period.
 *				This algorithm was benchmarked on a Gateway 2000 486/33C at
 *				29+ Kops (thousand operations per second).
 *			ALGORITHM_RANQD2
 *				A quick and dirty algorithm.  Use this algorithm if speed is an
 *				issue and the period of the random sequence is unimportant.
 *				This algorithm was benchmarked on a Gateway 2000 486/33C at
 *				49+ Kops (thousand operations per second).
 *			ALGORITHM_RAN4
 *				A slow algorithm with an exceptionally long period.
 *				This algorithm was benchmarked on a Gateway 2000 486/33C at
 *				18+ Kops (thousand operations per second).
 *		seed (i)
 *			A value used to seed the random number generator.  If the seed value
 *			is zero, the random number generator object will use a random seed
 *			value based on the time. 
 *
 *	Return Value:
 *		None.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

/*
 *	~RandomNumberGenerator ()
 *
 *	Public
 *
 *	Functional Description:
 *		This is the destructor for the RandomNumberGenerator class.
 *
 *	Formal Parameters:
 *		None.
 *
 *	Return Value:
 *		None.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

/*
 *	RandomValue		GetRandomNumber (
 *							RandomValue 	lo_extent,
 *							RandomValue		hi_extent)
 *
 *	Public
 *
 *	Functional Description:
 *		This method is used to generate a random number between the 
 *		specified values.
 *
 *	Formal Parameters:
 *		lo_extent (i)
 *			The lowest number you wish to receive.
 *		hi_extent (i)
 *			The highest number you wish to receive.
 *
 *	Return Value:
 *		A RandomValue in the range specified.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

/*
 *	Void		Reseed ()
 *
 *	Public
 *
 *	Functional Description:
 *		This method is used to reseed the random number generator object using
 *		the system time as the seed value.
 *
 *	Formal Parameters:
 *		None.
 *
 *	Return Value:
 *		None.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

/*
 *	Void	Reseed (
 *					ULong		seed)
 *
 *	Public
 *
 *	Functional Description:
 *		This method is used to reseed the random number generator object using
 *		the specified seed value.
 *
 *	Formal Parameters:
 *		seed (i)
 *			A value used to seed the random number generator.  If the seed value
 *			is zero, the random number generator object will use a random seed
 *			value based on the time. 
 *
 *	Return Value:
 *		None.
 *
 *	Side Effects:
 *		None.
 *
 *	Caveats:
 *		None.
 */

#endif	// USE_RANDOM_CLASS
#endif	// _RANDOM_
