"L. Spiro Engine"

F:/My Projects/LSEngine/Modules/LSMathLib/Src/Rand/LSMRand.h

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator