Humble Framework for SkyOS


Main Page | Modules | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

HRandom.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **  $Header: /SkyOS.root/pig/Humble/HRandom.h 3     12/10/04 3:57p Neusel $
00004 **
00005 ****************************************************************************/
00018 #ifndef HRANDOM_H
00019     #define HRANDOM_H
00020 
00057 class HRandom : public HObjNoCopy
00058     {
00059     typedef HObjNoCopy  base_class;
00060     static StringPtr    ClassName(void) { return "HRandom"; }
00061 
00062     enum    {
00063             kPeriod = 397,
00064             kLength = 624
00065             } bogus;
00066 /*  -----------------------------------------------------------------------
00067     VARIABLES
00068     ----------------------------------------------------------------------- */
00069 protected:
00070     int32               m_nLeft;        
00071     uint32              m_uSeed;        
00072     uint32 *            m_puNext;       
00073     uint32              m_uState[kLength+1];    
00074 /*  -----------------------------------------------------------------------
00075     CTOR / DTOR
00076     ----------------------------------------------------------------------- */
00077 public:
00078     HRandom(uint32 uSeed = 0) : m_nLeft(-1), m_uSeed(0), m_puNext(NULL)
00079         { if (uSeed) SetSeed(uSeed); }
00080 
00081     ~HRandom(void)
00082         { /* EMPTY DTOR */ }
00083 /*  -----------------------------------------------------------------------
00084     METHODS
00085     ----------------------------------------------------------------------- */
00086 protected:
00092     uint32
00093     reload(void)
00094         {
00095         int32       ndx;
00096         uint32      uS0, 
00097                     uS1;
00098         uint32 *    pu0 = m_uState;
00099         uint32 *    pu2 = &m_uState[2];
00100         uint32 *    puM = &m_uState[kPeriod];
00101 
00102         if (m_nLeft < -1)
00103             HError::Throw(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00104 
00105 #define hiBit(u)        ((u) & 0x80000000U)     // mask all but highest   bit of u
00106 #define loBit(u)        ((u) & 0x00000001U)     // mask all but lowest    bit of u
00107 #define loBits(u)       ((u) & 0x7FFFFFFFU)     // mask     the highest   bit of u
00108 #define mixBits(u,v)    (hiBit(u) | loBits(v))  // move hi bit of u to hi bit of v
00109 
00110         m_nLeft = kLength - 1;
00111         m_puNext = m_uState + 1;
00112 
00113         uS0 = m_uState[0];
00114         uS1 = m_uState[1];
00115         for (ndx = (kLength - kPeriod) + 1; --ndx; uS0 = uS1, uS1 = *pu2++)
00116             *pu0++ = *puM++ ^ (mixBits(uS0, uS1) >> 1) ^ (loBit(uS1) ? 0x9908B0DFU : 0U);
00117 
00118         for (puM = m_uState, ndx = kPeriod; --ndx; uS0 = uS1, uS1 = *pu2++)
00119             *pu0++ = *puM++ ^ (mixBits(uS0, uS1) >> 1) ^ (loBit(uS1) ? 0x9908B0DFU : 0U);
00120 
00121         uS1 = m_uState[0];
00122         *pu0 = *puM ^ (mixBits(uS0, uS1) >> 1) ^ (loBit(uS1) ? 0x9908B0DFU : 0U);
00123         uS1 ^= (uS1 >> 11);
00124         uS1 ^= (uS1 <<  7) & 0x9D2C5680U;
00125         uS1 ^= (uS1 << 15) & 0xEFC60000U;
00126 
00127         return uS1 ^ (uS1 >> 18);
00128         }
00129 /*  -----------------------------------------------------------------------
00130     GETTERS & SETTERS
00131     ----------------------------------------------------------------------- */
00132 public: 
00138     uint32              Get(void)
00139                             {
00140                             uint32  uiRnd;
00141 
00142                             if (--m_nLeft >= 0)
00143                                 {
00144                                 uiRnd  = *m_puNext++;
00145                                 uiRnd ^= (uiRnd >> 11);
00146                                 uiRnd ^= (uiRnd <<  7) & 0x9D2C5680U;
00147                                 uiRnd ^= (uiRnd << 15) & 0xEFC60000U;
00148                                 uiRnd ^= (uiRnd >> 18);
00149                                 }
00150                             else
00151                                 uiRnd = reload();
00152 
00153                             return uiRnd;
00154                             }
00161     uint32              Get(uint32 uMax)
00162                             {
00163                             uint32  uRnd = Get();
00164 
00165                             if (uMax == 1)  // special case is a 0/1 coin flip
00166                                 uRnd &= 0x01;
00167                             else if (uMax < uint32(INT32_MAX))
00168                                 uRnd %= uMax;
00169 
00170                             return uRnd;
00171                             }
00187     int32               Get(uint32 uCount, uint32 uDieSize, int32 nBonus = 0)
00188                             {
00189                             int32   nRnd = nBonus * uCount;
00190                         
00191                             if (uCount > 0 && uDieSize > 0)
00192                                 {
00193                                 ASSERT(uCount < uint32(INT32_MAX));
00194                                 ASSERT(uDieSize < uint32(INT32_MAX));
00195                             
00196                                 while (uCount-- > 0)
00197                                     nRnd += Get(uDieSize) + 1;
00198                                 }
00199                             
00200                             return nRnd;
00201                             }
00207     uint32              GetSeed(void) const
00208                             { return m_uSeed; }
00215     ErrCode             SetSeed(uint32 uSeed)
00216                             {
00217                             uint32 *    puState = m_uState;
00218 
00219                             DEBUG_LOG("HRandom::SetSeed() => seed value is %lu\n", uSeed);
00220 
00221                             m_uSeed = uSeed;
00222                             uSeed |= 1U;
00223                             for (int32 ndx = 0; ndx < kLength; ++ndx)
00224                                 {
00225                                 *puState++ = uSeed;
00226                                 uSeed *= 69069U;
00227                                 }
00228 /*                              
00229                             *puState++ = uSeed;
00230                             for (int32 ndx = kLength; --ndx > 0; *puState++ = uSeed)
00231                                 uSeed *= 69069U;
00232 */
00233                             m_nLeft = 0;
00234                             return HError::NoError();
00235                             }
00236     };
00237 
00238 #endif  // HRANDOM_H
00239 /****************************************************************************
00240 **
00241 **  $History: HRandom.h $
00242  * 
00243  * *****************  Version 3  *****************
00244  * User: Neusel       Date: 12/10/04   Time: 3:57p
00245  * Updated in $/SkyOS.root/pig/Humble
00246  * 20041210
00247  * 
00248  * *****************  Version 2  *****************
00249  * User: Neusel       Date: 11/30/04   Time: 1:01p
00250  * Updated in $/SkyOS.root/pig/Humble
00251  * Released as HUMBLE_VER 20041130.
00252  * 
00253  * *****************  Version 1  *****************
00254  * User: Neusel       Date: 11/23/04   Time: 8:24a
00255  * Created in $/SkyOS.root/pig/Humble
00256 **
00257 **  -------------------------------------------------------------------------
00258 **
00259 **  End of HRandom.h
00260 **
00261 ****************************************************************************/