"L. Spiro Engine"
|
00001 00027 #ifndef __LSM_RAND_H__ 00028 #define __LSM_RAND_H__ 00029 00030 #include "../LSMMathLib.h" 00031 00032 #if defined( LSE_VISUALSTUDIO ) 00033 #pragma warning( push ) 00034 00035 // warning C4146: unary minus operator applied to unsigned type, result still unsigned 00036 #pragma warning( disable : 4146 ) 00037 #endif // #if defined( LSE_VISUALSTUDIO ) 00038 00039 namespace lsm { 00040 00048 class CRand { 00049 public : 00050 // == Various constructors. 00051 LSE_INLINE LSE_CALLCTOR CRand(); 00052 00053 00054 // == Types. 00058 enum { 00059 LSM_STATE_LEN = 624, 00060 LSM_STATE_LEN_ARRAY 00061 }; 00062 00063 00064 // == Functions. 00070 LSVOID LSE_FCALL Seed( LSUINT32 _ui32Seed ); 00071 00077 LSUINT32 LSE_FCALL RandUInt32() const; 00078 00086 LSUINT32 LSE_FCALL RandUInt32( LSUINT32 _ui32Max ) const; 00087 00093 LSUINT64 LSE_FCALL RandUInt64() const; 00094 00102 LSUINT64 LSE_FCALL RandUInt64( LSUINT64 _ui64Max ) const; 00103 00109 LSREAL LSE_FCALL RandReal() const; 00110 00118 LSREAL LSE_FCALL RandReal( LSREAL _fLow, LSREAL _fHigh ) const; 00119 00120 protected : 00121 // == Types. 00125 enum { 00126 LSM_PERIOD = 397 00127 }; 00128 00129 00130 // == Members. 00131 // State array. 00132 mutable LSUINT32 m_ui32State[LSM_STATE_LEN_ARRAY]; 00133 00134 // Next value to get from the state. 00135 mutable LSUINT32 * m_pui32NextInState; 00136 00137 // Values left in the state before a reload is required. 00138 mutable LSINT32 m_i32LeftInState; 00139 00140 00141 // == Functions. 00147 LSVOID LSE_FCALL Initialize( LSUINT32 _ui32Seed ) const; 00148 00152 LSVOID LSE_FCALL Reload() const; 00153 00160 static LSUINT32 LSE_FCALL HiBit( const LSUINT32 & _ui32Val ); 00161 00168 static LSUINT32 LSE_FCALL LoBit( const LSUINT32 & _ui32Val ); 00169 00176 static LSUINT32 LSE_FCALL LoBits( const LSUINT32 & _ui32Val ); 00177 00185 static LSUINT32 LSE_FCALL MixBits( const LSUINT32 & _ui32L, const LSUINT32 & _ui32R ); 00186 00195 static LSUINT32 LSE_FCALL MersenneTwist( const LSUINT32 & _ui32F, const LSUINT32 & _ui32L, const LSUINT32 & _ui32R ); 00196 }; 00197 00198 00199 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00200 // DEFINITIONS 00201 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00202 // == Various constructors. 00203 LSE_INLINE LSE_CALLCTOR CRand::CRand() : 00204 m_pui32NextInState( NULL ), 00205 m_i32LeftInState( LSM_STATE_LEN_ARRAY ) { 00206 Seed( 19650218 ); 00207 } 00208 00209 // == Functions. 00215 LSE_INLINE LSVOID LSE_FCALL CRand::Seed( LSUINT32 _ui32Seed ) { 00216 Initialize( _ui32Seed ); 00217 Reload(); 00218 } 00219 00225 LSE_INLINE LSUINT32 LSE_FCALL CRand::RandUInt32() const { 00226 if ( m_i32LeftInState == 0 ) { Reload(); } 00227 --m_i32LeftInState; 00228 00229 LSUINT32 ui32Val; 00230 ui32Val = (*m_pui32NextInState++); 00231 ui32Val ^= (ui32Val >> 11); 00232 ui32Val ^= (ui32Val << 7) & 0x9D2C5680UL; 00233 ui32Val ^= (ui32Val << 15) & 0xEFC60000UL; 00234 return (ui32Val ^ (ui32Val >> 18)); 00235 } 00236 00244 LSE_INLINE LSUINT32 LSE_FCALL CRand::RandUInt32( LSUINT32 _ui32Max ) const { 00245 return static_cast<LSUINT32>(RandUInt32() * (static_cast<LSDOUBLE>(1.0 / 4294967296.0)) * _ui32Max); 00246 } 00247 00253 LSE_INLINE LSUINT64 LSE_FCALL CRand::RandUInt64() const { 00254 LSUINT64 ui64High = RandUInt32(); 00255 return RandUInt32() | (ui64High << 32ULL); 00256 } 00257 00265 LSE_INLINE LSUINT64 LSE_FCALL CRand::RandUInt64( LSUINT64 _ui64Max ) const { 00266 // If the range can be supported by RandUInt32(), revert to that. 00267 if ( _ui64Max <= (1ULL << 32ULL) ) { return RandUInt32( static_cast<LSUINT32>(_ui64Max) ); } 00268 // Otherwise the low part can be any random number and the high part is capped. 00269 LSUINT64 ui64High = RandUInt32( static_cast<LSUINT32>(_ui64Max >> 32ULL) ); 00270 return RandUInt32() | (ui64High << 32ULL); 00271 } 00272 00278 LSE_INLINE LSREAL LSE_FCALL CRand::RandReal() const { 00279 return static_cast<LSREAL>(RandUInt32() * (static_cast<LSDOUBLE>(1.0 / 4294967295.0))); 00280 } 00281 00289 LSE_INLINE LSREAL LSE_FCALL CRand::RandReal( LSREAL _fLow, LSREAL _fHigh ) const { 00290 return _fLow + RandReal() * (_fHigh - _fLow); 00291 } 00292 00298 LSE_INLINE LSVOID LSE_FCALL CRand::Initialize( LSUINT32 _ui32Seed ) const { 00299 LSUINT32 * pui32Cur = m_ui32State; 00300 LSUINT32 * pui32Next = m_ui32State; 00301 (*pui32Next++) = _ui32Seed; 00302 for ( LSUINT32 I = 1; I < LSM_STATE_LEN_ARRAY; ++I ) { 00303 (*pui32Next++) = (1812433253 * ((*pui32Cur) ^ ((*pui32Cur) >> 30)) + I) & 0xFFFFFFFF; 00304 ++pui32Cur; 00305 } 00306 } 00307 00311 LSE_INLINE LSVOID LSE_FCALL CRand::Reload() const { 00312 00313 LSUINT32 * pui32Cur = m_ui32State; 00314 for ( LSUINT32 I = LSM_STATE_LEN_ARRAY - LSM_PERIOD; I--; ++pui32Cur ) { 00315 (*pui32Cur) = MersenneTwist( pui32Cur[LSM_PERIOD], pui32Cur[0], pui32Cur[1] ); 00316 } 00317 for ( LSUINT32 I = LSM_PERIOD; --I; ++pui32Cur ) { 00318 (*pui32Cur) = MersenneTwist( pui32Cur[LSM_PERIOD-LSM_STATE_LEN_ARRAY], pui32Cur[0], pui32Cur[1] ); 00319 } 00320 (*pui32Cur) = MersenneTwist( pui32Cur[LSM_PERIOD-LSM_STATE_LEN_ARRAY], pui32Cur[0], m_ui32State[0] ); 00321 00322 m_i32LeftInState = LSM_STATE_LEN_ARRAY; 00323 m_pui32NextInState = m_ui32State; 00324 } 00325 00326 00333 LSE_INLINE LSUINT32 LSE_FCALL CRand::HiBit( const LSUINT32 & _ui32Val ) { 00334 return _ui32Val & 0x80000000; 00335 } 00336 00343 LSE_INLINE LSUINT32 LSE_FCALL CRand::LoBit( const LSUINT32 & _ui32Val ) { 00344 return _ui32Val & 0x00000001; 00345 } 00346 00353 LSE_INLINE LSUINT32 LSE_FCALL CRand::LoBits( const LSUINT32 & _ui32Val ) { 00354 return _ui32Val & 0x7FFFFFFF; 00355 } 00356 00364 LSE_INLINE LSUINT32 LSE_FCALL CRand::MixBits( const LSUINT32 & _ui32L, const LSUINT32 & _ui32R ) { 00365 return HiBit( _ui32L ) | LoBits( _ui32R ); 00366 } 00367 00376 LSE_INLINE LSUINT32 LSE_FCALL CRand::MersenneTwist( const LSUINT32 & _ui32F, const LSUINT32 & _ui32L, const LSUINT32 & _ui32R ) { 00377 return _ui32F ^ (MixBits( _ui32L, _ui32R ) >> 1) ^ (-LoBit( _ui32R ) & 0x9908B0DF); 00378 } 00379 00380 } // namespace lsm 00381 00382 00383 #if defined( LSE_VISUALSTUDIO ) 00384 #pragma warning( pop ) 00385 #endif // #if defined( LSE_VISUALSTUDIO ) 00386 00387 #endif // __LSM_RAND_H__