// DWBS ------------------------------------------------------------------ DWBS
//
// PLATFORM		: ALL
// PRODUCT		: BIT_DEMON
// VISIBILITY	: PUBLIC
//
// DWBS ------------------------------------------------------------------ DWBS

// PURPOSE: A class that generates deterministic pseudo-random.

#ifndef BD_RANDOM_H
#define BD_RANDOM_H

#include <bdCore/bdMemory/bdMemory.h>

#define BD_MAX_RANDOM (2147483647)

/// A class that generates deterministic pseudo-random.
/// This class uses integer arithmetic to generate pseudo-random numbers.
/// The distance between \f$(x_1,y_1)\f$ and \f$(x_2,y_2)\f$ is \f$\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}\f$.
/// The formula used to generate the number sequence is as follows:
/// \f[
/// \textrm{rand} =
/// 16807 \times (\textrm{seed} \  mod \ 127773) - 2836 \times (\textrm{seed} \div 127773),  \ \ \ \  \textrm{rand} > 0
/// \f]
/// \f[
/// \textrm{rand} =
/// 16807 \times (\textrm{seed} \  mod \ 127773) - 2836 \times  (\textrm{seed} \div 127773) + \textrm{MAX\_INT},  \ \ \ \ \textrm{otherwise}
/// \f]
class bdRandom
{
	public:

		BD_DECLARE_NEW_AND_DELETE_OPERATORS

		/// Default constructor.
		/// Uses the current time as the seed.
		bdRandom();

		/// Constructor that takes a seed argument.
		/// Enables this instance of bdRandom to be synchronized with the
		/// sequence generated by another bdRandom.
		/// \param	seed[in]	The seed to use when creating this object.
		bdRandom(const bdUInt seed);

		// Destructor.
		~bdRandom();

		/// Get the next unsigned integer in the random sequence.
		/// \return	The next random unsigned integer
		bdUInt nextUInt();

		/// Fill an array of bytes of a specified size with random bytes.
		/// \param	in[out]		The byte array to fill in.
		/// \param	length[in]	The size of the array.
		void nextUBytes(bdUByte8 in[],
						const bdInt length);

		/// Explicitly set a seed.
		/// \param	seed[in]	The seed to use when generating random numbers.
		/// \note	This method has immediate effect, and future calls to
		///			nextUInt() and nextUBytes() will be based off \a seed.
		void setSeed(const bdUInt seed);

		/// Get the seed for the next number.
		/// \return The seed to be used for the next number.
		bdUInt getSeed() const;

	protected:

		/// The seed for the next number.
		bdUInt m_val;

		/// Constant for the generation of the pseudo random sequence.
		static const bdInt a;
		/// Constant for the generation of the pseudo random sequence.
		static const bdInt m;
		/// Constant for the generation of the pseudo random sequence.
		static const bdInt q;
		/// Constant for the generation of the pseudo random sequence.
		static const bdInt r;
};

#endif // BD_RANDOM_H
