Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgRandom.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgRandom.h
00003     Random numbers. */
00004 //----------------------------------------------------------------------------
00005 
00006 #ifndef SG_RANDOM_H
00007 #define SG_RANDOM_H
00008 
00009 #include <algorithm>
00010 #include <list>
00011 #include <boost/random/mersenne_twister.hpp>
00012 #include "SgArray.h"
00013 
00014 //----------------------------------------------------------------------------
00015 
00016 /** Random number generator.
00017     Uses a Mersenne Twister, because this is faster than std::rand() and
00018     game playing programs usually need faster random numbers more than
00019     high quality ones. All random generators are internally registered to
00020     make it possible to change the random seed for all of them.
00021 
00022     SgRandom is thread-safe (w.r.t. different instances) after construction
00023     (the constructor is not thread-safe, because it uses a global variable
00024     for registration). */
00025 class SgRandom
00026 {
00027 public:
00028     SgRandom();
00029 
00030     ~SgRandom();
00031 
00032     /** Return the global random number generator.
00033         The global generator is stored as a static variable in this function
00034         to ensure that it is initialized at first call if SgRandom is used
00035         in global variables of other compilation units.
00036         @note The global random number generator is not thread-safe. */
00037     static SgRandom& Global();
00038 
00039     /** Set random seed for all existing and future instances of SgRandom.
00040         @param seed The seed. If negative, no seed will be set. If zero, a
00041         non-deterministic random seed will be used (e.g. derived from the
00042         current time).
00043         Also calls std::srand()
00044         @note This function is not thread-safe. */
00045     static void SetSeed(int seed);
00046 
00047     /** Get random seed.
00048         See SetSeed(int) for the special meaning of zero and negative values. */
00049     static int Seed();
00050 
00051     /** Get a random integer.
00052         Uses a fast random generator (the Mersenne Twister boost::mt19937),
00053         because in games and Monte Carlo simulations, speed is more important
00054         than quality. */
00055     unsigned int Int();
00056 
00057     /** Get a random integer in an interval.
00058         @param range The upper limit of the interval (exclusive)
00059         @pre range > 0
00060         @pre range <= SgRandom::Max()
00061         @return An integer in <tt> [0..range - 1]</tt> */
00062     int Int(int range);
00063 
00064     /** See SgRandom::Int(int) */
00065     std::size_t Int(std::size_t range);
00066 
00067     /** Get a small random integer in an interval.
00068         Uses only the lower 16 bits. Faster than SgRandom::Int(int) because it
00069         avoids the expensive modulo operation.
00070         @param range The upper limit of the interval (exclusive)
00071         @pre range > 0
00072         @pre range <= (1 << 16)
00073         @return An integer in <tt> [0..range - 1]</tt> */
00074     int SmallInt(int range);
00075 
00076     /** See SgRandom::SmallInt(int) */
00077     std::size_t SmallInt(std::size_t range);
00078 
00079     /** Get a random integer in [min, max - 1] */
00080     int Range(int min, int max);
00081 
00082     /** Maximum value. */
00083     unsigned int Max();
00084 
00085     /** convert percentage between 0 and 99 to a threshold for RandomEvent.
00086         Use as in following example:
00087         const unsigned int percent80 = PercentageThreshold(80); */
00088     unsigned int PercentageThreshold(int percentage);
00089 
00090     /** return true if random number SgRandom() <= threshold */
00091     bool RandomEvent(unsigned int threshold);
00092 
00093 private:
00094     struct GlobalData
00095     {
00096         /** The random seed.
00097             Zero means not to set a random seed. */
00098         boost::mt19937::result_type m_seed;
00099 
00100         std::list<SgRandom*> m_allGenerators;
00101 
00102         GlobalData();
00103     };
00104 
00105     /** Return global data.
00106         Global data is stored as a static variable in this function to ensure
00107         that it is initialized at first call if SgRandom is used in global
00108         variables of other compilation units. */
00109     static GlobalData& GetGlobalData();
00110 
00111     boost::mt19937 m_generator;
00112 
00113     void SetSeed();
00114 };
00115 
00116 inline unsigned int SgRandom::Int()
00117 {
00118     return m_generator();
00119 }
00120 
00121 inline int SgRandom::Int(int range)
00122 {
00123     SG_ASSERT(range > 0);
00124     SG_ASSERT(static_cast<unsigned int>(range) <= SgRandom::Max());
00125     int i = Int() % range;
00126     SG_ASSERTRANGE(i, 0, range - 1);
00127     return i;
00128 }
00129 
00130 inline std::size_t SgRandom::Int(std::size_t range)
00131 {
00132     SG_ASSERT(range <= SgRandom::Max());
00133     std::size_t i = Int() % range;
00134     SG_ASSERT(i < range);
00135     return i;
00136 }
00137 
00138 inline unsigned int SgRandom::Max()
00139 {
00140     return m_generator.max();
00141 }
00142 
00143 inline unsigned int SgRandom::PercentageThreshold(int percentage)
00144 {
00145     return (m_generator.max() / 100) * percentage;
00146 }
00147 
00148 inline bool SgRandom::RandomEvent(unsigned int threshold)
00149 {
00150     return Int() <= threshold;
00151 }
00152 
00153 inline int SgRandom::Range(int min, int max)
00154 {
00155     return min + Int(max - min);
00156 }
00157 
00158 inline int SgRandom::SmallInt(int range)
00159 {
00160     SG_ASSERT(range > 0);
00161     SG_ASSERT(range <= (1 << 16));
00162     int i = ((Int() & 0xffff) * range) >> 16;
00163     SG_ASSERTRANGE(i, 0, range - 1);
00164     return i;
00165 }
00166 
00167 inline std::size_t SgRandom::SmallInt(std::size_t range)
00168 {
00169     SG_ASSERT(range <= (1 << 16));
00170     std::size_t i = ((Int() & 0xffff) * range) >> 16;
00171     SG_ASSERT(i < range);
00172     return i;
00173 }
00174 
00175 //----------------------------------------------------------------------------
00176 
00177 /** Get a random float in [min, max].
00178     Used std::rand() */
00179 float SgRandomFloat(float min, float max);
00180 
00181 //----------------------------------------------------------------------------
00182 
00183 #endif // SG_RANDOM_H


Sun Mar 13 2011 Doxygen 1.7.1