/* ** m_random.h ** Random number generators ** **--------------------------------------------------------------------------- ** Copyright 2002-2009 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** 3. The name of the author may not be used to endorse or promote products ** derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **--------------------------------------------------------------------------- ** */ #ifndef __M_RANDOM__ #define __M_RANDOM__ #include #include "basictypes.h" #include "sfmt/SFMT.h" class FSerializer; class FRandom { public: FRandom (); FRandom (const char *name); ~FRandom (); // Returns a random number in the range [0,255] int operator()() { return GenRand32() & 255; } // Returns a random number in the range [0,mod) int operator() (int mod) { return (0 == mod) ? 0 : (GenRand32() % mod); } // Returns rand# - rand# int Random2() { return Random2(255); } // Returns (rand# & mask) - (rand# & mask) int Random2(int mask) { int t = GenRand32() & mask & 255; return t - (GenRand32() & mask & 255); } // HITDICE macro used in Heretic and Hexen int HitDice(int count) { return (1 + (GenRand32() & 7)) * count; } int Random() // synonym for () { return operator()(); } void Init(DWORD seed); // SFMT interface unsigned int GenRand32(); QWORD GenRand64(); void FillArray32(DWORD *array, int size); void FillArray64(QWORD *array, int size); void InitGenRand(DWORD seed); void InitByArray(DWORD *init_key, int key_length); int GetMinArraySize32(); int GetMinArraySize64(); /* These real versions are due to Isaku Wada */ /** generates a random number on [0,1]-real-interval */ static inline double ToReal1(DWORD v) { return v * (1.0/4294967295.0); /* divided by 2^32-1 */ } /** generates a random number on [0,1]-real-interval */ inline double GenRand_Real1() { return ToReal1(GenRand32()); } /** generates a random number on [0,1)-real-interval */ static inline double ToReal2(DWORD v) { return v * (1.0/4294967296.0); /* divided by 2^32 */ } /** generates a random number on [0,1)-real-interval */ inline double GenRand_Real2() { return ToReal2(GenRand32()); } /** generates a random number on (0,1)-real-interval */ static inline double ToReal3(DWORD v) { return (((double)v) + 0.5)*(1.0/4294967296.0); /* divided by 2^32 */ } /** generates a random number on (0,1)-real-interval */ inline double GenRand_Real3(void) { return ToReal3(GenRand32()); } /** These real versions are due to Isaku Wada */ /** generates a random number on [0,1) with 53-bit resolution*/ static inline double ToRes53(QWORD v) { return v * (1.0/18446744073709551616.0L); } /** generates a random number on [0,1) with 53-bit resolution from two * 32 bit integers */ static inline double ToRes53Mix(DWORD x, DWORD y) { return ToRes53(x | ((QWORD)y << 32)); } /** generates a random number on [0,1) with 53-bit resolution */ inline double GenRand_Res53(void) { return ToRes53(GenRand64()); } /** generates a random number on [0,1) with 53-bit resolution using 32bit integer. */ inline double GenRand_Res53_Mix() { DWORD x, y; x = GenRand32(); y = GenRand32(); return ToRes53Mix(x, y); } // Static interface static void StaticClearRandom (); static DWORD StaticSumSeeds (); static void StaticReadRNGState (FSerializer &arc); static void StaticWriteRNGState (FSerializer &file); static FRandom *StaticFindRNG(const char *name); #ifndef NDEBUG static void StaticPrintSeeds (); #endif private: #ifndef NDEBUG const char *Name; #endif FRandom *Next; DWORD NameCRC; static FRandom *RNGList; /*------------------------------------------- SFMT internal state, index counter and flag -------------------------------------------*/ void GenRandAll(); void GenRandArray(w128_t *array, int size); void PeriodCertification(); /** the 128-bit internal state array */ union { w128_t w128[SFMT::N]; unsigned int u[SFMT::N32]; QWORD u64[SFMT::N64]; } sfmt; /** index counter to the 32-bit internal state array */ int idx; /** a flag: it is 0 if and only if the internal state is not yet * initialized. */ #ifndef NDEBUG bool initialized; #endif }; extern DWORD rngseed; // The starting seed (not part of state) extern DWORD staticrngseed; // Static rngseed that can be set by the user extern bool use_staticrng; // M_Random can be used for numbers that do not affect gameplay extern FRandom M_Random; #endif