VirtualBox

Changeset 11347

Show
Ignore:
Timestamp:
08/11/08 23:12:55 (3 months ago)
Author:
vboxsync
Message:

iprt/rand: Added a generic RTRandAdv API for use with any random number generator. Implemented the classic Park-Miller pseudo random number generator.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/iprt/rand.h

    r11018 r11347  
    113113RTDECL(uint64_t) RTRandU64(void) RT_NO_THROW; 
    114114 
     115 
     116/** 
     117 * Create an instance of the default random number generator. 
     118 * 
     119 * @returns IPRT status code. 
     120 * @param   hRand       Handle to the random number generator. 
     121 */ 
     122RTDECL(int) RTRandAdvCreate(PRTRAND phRand) RT_NO_THROW; 
     123 
     124/** 
     125 * Create an instance of the default pseudo random number generator. 
     126 * 
     127 * @returns IPRT status code. 
     128 * @param   phRand      Where to store the handle to the generator. 
     129 */ 
     130RTDECL(int) RTRandAdvCreatePseudo(PRTRAND phRand) RT_NO_THROW; 
     131 
     132 
     133/** 
     134 * Create an instance of the Park-Miller pseudo random number generator. 
     135 * 
     136 * @returns IPRT status code. 
     137 * @param   phRand      Where to store the handle to the generator. 
     138 */ 
     139RTDECL(int) RTRandAdvCreateParkMiller(PRTRAND phRand) RT_NO_THROW; 
     140 
     141/** 
     142 * Destroys a random number generator. 
     143 * 
     144 * @returns IPRT status code. 
     145 * @param   hRand       Handle to the random number generator. 
     146 */ 
     147RTDECL(int) RTRandAdvDestroy(RTRAND hRand) RT_NO_THROW; 
     148 
     149/** 
     150 * Generic method for seeding of a random number generator. 
     151 * 
     152 * The different generators may have specialized methods for 
     153 * seeding, use one of those if you desire better control 
     154 * over ther result. 
     155 * 
     156 * @returns IPRT status code. 
     157 * @param   hRand       Handle to the random number generator. 
     158 * @param   u64Seed     Seed. 
     159 */ 
     160RTDECL(int) RTRandAdvSeed(RTRAND hRand, uint64_t u64Seed) RT_NO_THROW; 
     161 
     162/** 
     163 * Fills a buffer with random bytes. 
     164 * 
     165 * @param   hRand       Handle to the random number generator. 
     166 * @param   pv  Where to store the random bytes. 
     167 * @param   cb  Number of bytes to generate. 
     168 */ 
     169RTDECL(void) RTRandAdvBytes(RTRAND hRand, void *pv, size_t cb) RT_NO_THROW; 
     170 
     171/** 
     172 * Generate a 32-bit signed random number in the set [i32First..i32Last]. 
     173 * 
     174 * @returns The random number. 
     175 * @param   hRand       Handle to the random number generator. 
     176 * @param   i32First    First number in the set. 
     177 * @param   i32Last     Last number in the set. 
     178 */ 
     179RTDECL(int32_t) RTRandAdvS32Ex(RTRAND hRand, int32_t i32First, int32_t i32Last) RT_NO_THROW; 
     180 
     181/** 
     182 * Generate a 32-bit signed random number. 
     183 * 
     184 * @returns The random number. 
     185 * @param   hRand       Handle to the random number generator. 
     186 */ 
     187RTDECL(int32_t) RTRandAdvS32(RTRAND hRand) RT_NO_THROW; 
     188 
     189/** 
     190 * Generate a 32-bit unsigned random number in the set [u32First..u32Last]. 
     191 * 
     192 * @returns The random number. 
     193 * @param   hRand       Handle to the random number generator. 
     194 * @param   u32First    First number in the set. 
     195 * @param   u32Last     Last number in the set. 
     196 */ 
     197RTDECL(uint32_t) RTRandAdvU32Ex(RTRAND hRand, uint32_t u32First, uint32_t u32Last) RT_NO_THROW; 
     198 
     199/** 
     200 * Generate a 32-bit unsigned random number. 
     201 * 
     202 * @returns The random number. 
     203 * @param   hRand       Handle to the random number generator. 
     204 */ 
     205RTDECL(uint32_t) RTRandAdvU32(RTRAND hRand) RT_NO_THROW; 
     206 
     207/** 
     208 * Generate a 64-bit signed random number in the set [i64First..i64Last]. 
     209 * 
     210 * @returns The random number. 
     211 * @param   hRand       Handle to the random number generator. 
     212 * @param   i64First    First number in the set. 
     213 * @param   i64Last     Last number in the set. 
     214 */ 
     215RTDECL(int64_t) RTRandAdvS64Ex(RTRAND hRand, int64_t i64First, int64_t i64Last) RT_NO_THROW; 
     216 
     217/** 
     218 * Generate a 64-bit signed random number. 
     219 * 
     220 * @returns The random number. 
     221 */ 
     222RTDECL(int64_t) RTRandAdvS64(RTRAND hRand) RT_NO_THROW; 
     223 
     224/** 
     225 * Generate a 64-bit unsigned random number in the set [u64First..u64Last]. 
     226 * 
     227 * @returns The random number. 
     228 * @param   hRand       Handle to the random number generator. 
     229 * @param   u64First    First number in the set. 
     230 * @param   u64Last     Last number in the set. 
     231 */ 
     232RTDECL(uint64_t) RTRandAdvU64Ex(RTRAND hRand, uint64_t u64First, uint64_t u64Last) RT_NO_THROW; 
     233 
     234/** 
     235 * Generate a 64-bit unsigned random number. 
     236 * 
     237 * @returns The random number. 
     238 * @param   hRand       Handle to the random number generator. 
     239 */ 
     240RTDECL(uint64_t) RTRandAdvU64(RTRAND hRand) RT_NO_THROW; 
     241 
     242 
    115243/** @} */ 
    116244 
  • trunk/include/iprt/types.h

    r11308 r11347  
    11471147#define NIL_RTTIMERLR                               ((RTTIMERLR)0) 
    11481148 
     1149/** Handle to a random number generator. */ 
     1150typedef struct RTRANDINT                           *RTRAND; 
     1151/** Pointer to a random number generator handle. */ 
     1152typedef RTRAND                                     *PRTRAND; 
     1153/** NIL random number genrator handle value. */ 
     1154#define NIL_RTRAND                                  ((RTRAND)0) 
     1155 
    11491156 
    11501157/** 
  • trunk/src/VBox/Runtime/Makefile.kmk

    r11327 r11347  
    197197        common/misc/zip.cpp \ 
    198198        common/rand/rand.cpp \ 
     199        common/rand/randadv.cpp \ 
     200        common/rand/randparkmiller.cpp \ 
    199201        common/string/RTStrNLen.cpp \ 
    200202        common/string/RTStrNLenEx.cpp \ 
  • trunk/src/VBox/Runtime/include/internal/magics.h

    r10944 r11347  
    5555/** RTR0MEMOBJ::u32Magic. (Masakazu Katsura) */ 
    5656#define RTR0MEMOBJ_MAGIC            0x19611210 
     57/** RTRANDINT::u32Magic. (Alan Moore) */ 
     58#define RTRANDINT_MAGIC             0x19531118 
    5759/** Magic for the event semaphore structure. (Neil Gaiman) */ 
    5860#define RTSEMEVENT_MAGIC            0x19601110 
  • trunk/src/VBox/Runtime/include/internal/rand.h

    r11019 r11347  
    3333 
    3434#include <iprt/types.h> 
     35#include <iprt/critsect.h> 
     36 
     37/** Pointer to a random number generator instance. */ 
     38typedef struct RTRANDINT *PRTRANDINT; 
     39 
     40/** 
     41 * Random number generator instance. 
     42 * 
     43 * @remarks Not sure if it makes sense to have three random getters... 
     44 */ 
     45typedef struct RTRANDINT 
     46{ 
     47    /** Magic value (RTRANDINT_MAGIC). */ 
     48    uint32_t    u32Magic; 
     49#if 0 /** @todo later. */ 
     50    /** Fast mutex semaphore that serializes the access, this is optional. */ 
     51    PRTCRITSECT pCritSect; 
     52#endif 
     53 
     54    /** 
     55     * Generates random bytes. 
     56     * 
     57     * @param   pThis       Pointer to the instance data. 
     58     * @param   pb          Where to store the bytes. 
     59     * @param   cb          The number of bytes to produce. 
     60     */ 
     61    DECLCALLBACKMEMBER(void ,    pfnGetBytes)(PRTRANDINT pThis, uint8_t *pb, size_t cb); 
     62 
     63    /** 
     64     * Generates a unsigned 32-bit random number. 
     65     * 
     66     * @returns The random number. 
     67     * @param   pThis       Pointer to the instance data. 
     68     * @param   u32First    The first number in the range. 
     69     * @param   u32Last     The last number in the range (i.e. inclusive). 
     70     */ 
     71    DECLCALLBACKMEMBER(uint32_t, pfnGetU32)(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last); 
     72 
     73    /** 
     74     * Generates a unsigned 64-bit random number. 
     75     * 
     76     * @returns The random number. 
     77     * @param   pThis       Pointer to the instance data. 
     78     * @param   u64First    The first number in the range. 
     79     * @param   u64Last     The last number in the range (i.e. inclusive). 
     80     */ 
     81    DECLCALLBACKMEMBER(uint64_t, pfnGetU64)(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last); 
     82 
     83    /** 
     84     * Generic seeding. 
     85     * 
     86     * @returns IPRT status code. 
     87     * @param   pThis       Pointer to the instance data. 
     88     * @param   u64Seed     The seed. 
     89     */ 
     90    DECLCALLBACKMEMBER(int, pfnSeed)(PRTRANDINT pThis, uint64_t u64Seed); 
     91 
     92    /** 
     93     * Destroys the instance. 
     94     * 
     95     * The callee is responsible for freeing all resources, including 
     96     * the instance data. 
     97     * 
     98     * @returns IPRT status code. State undefined on failure. 
     99     * @param   pThis       Pointer to the instance data. 
     100     */ 
     101    DECLCALLBACKMEMBER(int, pfnDestroy)(PRTRANDINT pThis); 
     102 
     103    /** Union containing the specific state info for each generator. */ 
     104    union 
     105    { 
     106        struct RTRandParkMiller 
     107        { 
     108            /** The context. */ 
     109            uint32_t    u32Ctx; 
     110            /** The number of single bits used to fill in the 31st bit. */ 
     111            uint32_t    u32Bits; 
     112            /** The number bits in u32Bits. */ 
     113            uint32_t    cBits; 
     114        } ParkMiller; 
     115    } u; 
     116} RTRANDINT; 
     117 
    35118 
    36119__BEGIN_DECLS 
     
    52135void rtRandGenBytesFallback(void *pv, size_t cb) RT_NO_THROW; 
    53136 
     137DECLCALLBACK(void)      rtRandAdvSynthesizeBytesFromU32(PRTRANDINT pThis, uint8_t *pb, size_t cb); 
     138DECLCALLBACK(void)      rtRandAdvSynthesizeBytesFromU64(PRTRANDINT pThis, uint8_t *pb, size_t cb); 
     139DECLCALLBACK(uint32_t)  rtRandAdvSynthesizeU32FromBytes(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last); 
     140DECLCALLBACK(uint32_t)  rtRandAdvSynthesizeU32FromU64(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last); 
     141DECLCALLBACK(uint64_t)  rtRandAdvSynthesizeU64FromBytes(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last); 
     142DECLCALLBACK(uint64_t)  rtRandAdvSynthesizeU64FromU32(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last); 
     143 
    54144__END_DECLS 
    55145 
    56146#endif 
     147 
  • trunk/src/VBox/Runtime/testcase/tstRand.cpp

    r11064 r11347  
    101101 
    102102 
    103 int main(
     103static int tstRandAdv(RTRAND hRand
    104104{ 
    105     RTR3Init(false); 
    106     RTPrintf("tstRand: TESTING...\n"); 
    107  
    108     /* 
    109      * Do some smoke tests first? 
    110      */ 
    111     /** @todo RTRand smoke testing. */ 
    112  
    113105    /* 
    114106     * Test distribution. 
     
    139131        uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); 
    140132        uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; 
    141         RTPrintf("tstRand: TESTING RTRandU32Ex(%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange); 
    142         for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
    143         { 
    144             uint32_t uRand = RTRandU32Ex(uFirst, uLast); 
     133        RTPrintf("tstRand:   TESTING RTRandAdvU32Ex(,%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange); 
     134        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     135        { 
     136            uint32_t uRand = RTRandAdvU32Ex(hRand, uFirst, uLast); 
    145137            CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst)); 
    146138            CHECK_EXPR_MSG(uRand <= uLast,  ("%#RX32 %#RX32\n", uRand, uLast)); 
     
    184176        uint64_t const uRange = uLast - uFirst;  Assert(uLast >= uFirst); 
    185177        uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; 
    186         RTPrintf("tstRand: TESTING RTRandU64Ex(%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange); 
    187         for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
    188         { 
    189             uint64_t uRand = RTRandU64Ex(uFirst, uLast); 
     178        RTPrintf("tstRand:   TESTING RTRandAdvU64Ex(,%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange); 
     179        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     180        { 
     181            uint64_t uRand = RTRandAdvU64Ex(hRand, uFirst, uLast); 
    190182            CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst)); 
    191183            CHECK_EXPR_MSG(uRand <= uLast,  ("%#RX64 %#RX64\n", uRand, uLast)); 
     
    242234        uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); 
    243235        uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1; 
    244         RTPrintf("tstRand: TESTING RTRandS32Ex(%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange); 
    245         for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
    246         { 
    247             int32_t iRand = RTRandS32Ex(iFirst, iLast); 
     236        RTPrintf("tstRand:   TESTING RTRandAdvS32Ex(,%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange); 
     237        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     238        { 
     239            int32_t iRand = RTRandAdvS32Ex(hRand, iFirst, iLast); 
    248240            CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst)); 
    249241            CHECK_EXPR_MSG(iRand <= iLast,  ("%#RI32 %#RI32\n", iRand, iLast)); 
     
    311303        uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); 
    312304        uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1; 
     305        RTPrintf("tstRand:   TESTING RTRandAdvS64Ex(,%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange); 
     306        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     307        { 
     308            int64_t iRand = RTRandAdvS64Ex(hRand, iFirst, iLast); 
     309            CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI64 %#RI64\n", iRand, iFirst)); 
     310            CHECK_EXPR_MSG(iRand <= iLast,  ("%#RI64 %#RI64\n", iRand, iLast)); 
     311            uint64_t off = iRand - iFirst; 
     312            acHits[off / uDivisor]++; 
     313        } 
     314        tstRandCheckDist(acHits, iTest); 
     315    } 
     316#endif 
     317 
     318    /* 
     319     * Destroy it. 
     320     */ 
     321    int rc = RTRandAdvDestroy(hRand); 
     322    CHECK_EXPR_MSG(rc == VINF_SUCCESS,  ("RTRandAdvDestroy(%p) -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); 
     323 
     324    return 0; 
     325} 
     326 
     327 
     328 
     329int main() 
     330{ 
     331    RTR3Init(false); 
     332    RTPrintf("tstRand: TESTING...\n"); 
     333 
     334    /* 
     335     * Do some smoke tests first? 
     336     */ 
     337    /** @todo RTRand smoke testing. */ 
     338 
     339#if 1 
     340    /* 
     341     * Test distribution. 
     342     */ 
     343#if 1 
     344    /* unsigned 32-bit */ 
     345    static const struct 
     346    { 
     347        uint32_t u32First; 
     348        uint32_t u32Last; 
     349    } s_aU32Tests[] = 
     350    { 
     351        { 0, UINT32_MAX }, 
     352        { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, 
     353        { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, 
     354        { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, 
     355        { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, 
     356        { 0, UINT32_MAX / 2 }, 
     357        { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, 
     358        { 0, TST_RAND_SAMPLE_RANGES - 1 }, 
     359        { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, 
     360    }; 
     361    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU32Tests); iTest++) 
     362    { 
     363        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0}; 
     364        uint32_t const uFirst = s_aU32Tests[iTest].u32First; 
     365        uint32_t const uLast  = s_aU32Tests[iTest].u32Last; 
     366        uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst); 
     367        uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; 
     368        RTPrintf("tstRand: TESTING RTRandU32Ex(%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange); 
     369        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     370        { 
     371            uint32_t uRand = RTRandU32Ex(uFirst, uLast); 
     372            CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst)); 
     373            CHECK_EXPR_MSG(uRand <= uLast,  ("%#RX32 %#RX32\n", uRand, uLast)); 
     374            uint32_t off = uRand - uFirst; 
     375            acHits[off / uDivisor]++; 
     376        } 
     377        tstRandCheckDist(acHits, iTest); 
     378    } 
     379#endif 
     380 
     381#if 1 
     382    /* unsigned 64-bit */ 
     383    static const struct 
     384    { 
     385        uint64_t u64First; 
     386        uint64_t u64Last; 
     387    } s_aU64Tests[] = 
     388    { 
     389        { 0, UINT64_MAX }, 
     390        { 0, UINT64_MAX / 2 + UINT64_MAX / 4 }, 
     391        { 0, UINT64_MAX / 2 + UINT64_MAX / 8 }, 
     392        { 0, UINT64_MAX / 2 + UINT64_MAX / 16 }, 
     393        { 0, UINT64_MAX / 2 + UINT64_MAX / 64 }, 
     394        { 0, UINT64_MAX / 2 }, 
     395        { UINT64_MAX / 4, UINT64_MAX / 4 * 3 }, 
     396        { 0, UINT32_MAX }, 
     397        { 0, UINT32_MAX / 2 + UINT32_MAX / 4 }, 
     398        { 0, UINT32_MAX / 2 + UINT32_MAX / 8 }, 
     399        { 0, UINT32_MAX / 2 + UINT32_MAX / 16 }, 
     400        { 0, UINT32_MAX / 2 + UINT32_MAX / 64 }, 
     401        { 0, UINT32_MAX / 2 }, 
     402        { UINT32_MAX / 4, UINT32_MAX / 4 * 3 }, 
     403        { 0, TST_RAND_SAMPLE_RANGES - 1 }, 
     404        { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 }, 
     405    }; 
     406    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU64Tests); iTest++) 
     407    { 
     408        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0}; 
     409        uint64_t const uFirst = s_aU64Tests[iTest].u64First; 
     410        uint64_t const uLast  = s_aU64Tests[iTest].u64Last; 
     411        uint64_t const uRange = uLast - uFirst;  Assert(uLast >= uFirst); 
     412        uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1; 
     413        RTPrintf("tstRand: TESTING RTRandU64Ex(%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange); 
     414        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     415        { 
     416            uint64_t uRand = RTRandU64Ex(uFirst, uLast); 
     417            CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst)); 
     418            CHECK_EXPR_MSG(uRand <= uLast,  ("%#RX64 %#RX64\n", uRand, uLast)); 
     419            uint64_t off = uRand - uFirst; 
     420            acHits[off / uDivisor]++; 
     421        } 
     422        tstRandCheckDist(acHits, iTest); 
     423    } 
     424#endif 
     425 
     426#if 1 
     427    /* signed 32-bit */ 
     428    static const struct 
     429    { 
     430        int32_t i32First; 
     431        int32_t i32Last; 
     432    } s_aS32Tests[] = 
     433    { 
     434        { -429496729, 429496729 }, 
     435        { INT32_MIN, INT32_MAX }, 
     436        { INT32_MIN, INT32_MAX / 2 }, 
     437        { -0x20000000, INT32_MAX }, 
     438        { -0x10000000, INT32_MAX }, 
     439        { -0x080000000, INT32_MAX }, 
     440        { -0x008000000, INT32_MAX }, 
     441        { -0x000800000, INT32_MAX }, 
     442        { -0x000080000, INT32_MAX }, 
     443        { -0x000008000, INT32_MAX }, 
     444        { 2, INT32_MAX / 2 }, 
     445        { 4000000, INT32_MAX / 2 }, 
     446        { -4000000, INT32_MAX / 2 }, 
     447        { INT32_MIN / 2, INT32_MAX / 2 }, 
     448        { INT32_MIN / 3, INT32_MAX / 2 }, 
     449        { INT32_MIN / 3, INT32_MAX / 3 }, 
     450        { INT32_MIN / 3, INT32_MAX / 4 }, 
     451        { INT32_MIN / 4, INT32_MAX / 4 }, 
     452        { INT32_MIN / 5, INT32_MAX / 5 }, 
     453        { INT32_MIN / 6, INT32_MAX / 6 }, 
     454        { INT32_MIN / 7, INT32_MAX / 6 }, 
     455        { INT32_MIN / 7, INT32_MAX / 7 }, 
     456        { INT32_MIN / 7, INT32_MAX / 8 }, 
     457        { INT32_MIN / 8, INT32_MAX / 8 }, 
     458        { INT32_MIN / 9, INT32_MAX / 9 }, 
     459        { INT32_MIN / 9, INT32_MAX / 12 }, 
     460        { INT32_MIN / 12, INT32_MAX / 12 }, 
     461        { 0, TST_RAND_SAMPLE_RANGES - 1 }, 
     462        { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 }, 
     463    }; 
     464    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS32Tests); iTest++) 
     465    { 
     466        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0}; 
     467        int32_t const  iFirst = s_aS32Tests[iTest].i32First; 
     468        int32_t const  iLast  = s_aS32Tests[iTest].i32Last; 
     469        uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); 
     470        uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1; 
     471        RTPrintf("tstRand: TESTING RTRandS32Ex(%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange); 
     472        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     473        { 
     474            int32_t iRand = RTRandS32Ex(iFirst, iLast); 
     475            CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst)); 
     476            CHECK_EXPR_MSG(iRand <= iLast,  ("%#RI32 %#RI32\n", iRand, iLast)); 
     477            uint32_t off = iRand - iFirst; 
     478            acHits[off / uDivisor]++; 
     479        } 
     480        tstRandCheckDist(acHits, iTest); 
     481    } 
     482#endif 
     483 
     484#if 1 
     485    /* signed 64-bit */ 
     486    static const struct 
     487    { 
     488        int64_t i64First; 
     489        int64_t i64Last; 
     490    } s_aS64Tests[] = 
     491    { 
     492        { INT64_MIN, INT64_MAX }, 
     493        { INT64_MIN, INT64_MAX / 2 }, 
     494        { INT64_MIN / 2, INT64_MAX / 2 }, 
     495        { INT64_MIN / 2 + INT64_MIN / 4, INT64_MAX / 2 }, 
     496        { INT64_MIN / 2 + INT64_MIN / 8, INT64_MAX / 2 }, 
     497        { INT64_MIN / 2 + INT64_MIN / 16, INT64_MAX / 2 }, 
     498        { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 }, 
     499        { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 + INT64_MAX / 64 }, 
     500        { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 64 }, 
     501        { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 8 }, 
     502        { INT64_MIN / 2, INT64_MAX / 2 - INT64_MAX / 8 }, 
     503        { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 4 }, 
     504        { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 8 }, 
     505        { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 - INT64_MAX / 8 }, 
     506        { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 8 }, 
     507        { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 16 }, 
     508        { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 16 }, 
     509        { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 32 }, 
     510        { INT64_MIN / 2 - INT64_MIN / 64, INT64_MAX / 2 - INT64_MAX / 64 }, 
     511        { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 }, 
     512        { INT64_MIN / 4, INT64_MAX / 4 }, 
     513        { INT64_MIN / 5, INT64_MAX / 5 }, 
     514        { INT64_MIN / 6, INT64_MAX / 6 }, 
     515        { INT64_MIN / 7, INT64_MAX / 7 }, 
     516        { INT64_MIN / 8, INT64_MAX / 8 }, 
     517        { INT32_MIN, INT32_MAX }, 
     518        { INT32_MIN, INT32_MAX / 2 }, 
     519        { -0x20000000, INT32_MAX }, 
     520        { -0x10000000, INT32_MAX }, 
     521        { -0x7f000000, INT32_MAX }, 
     522        { -0x08000000, INT32_MAX }, 
     523        { -0x00800000, INT32_MAX }, 
     524        { -0x00080000, INT32_MAX }, 
     525        { -0x00008000, INT32_MAX }, 
     526        { 2, INT32_MAX / 2 }, 
     527        { 4000000, INT32_MAX / 2 }, 
     528        { -4000000, INT32_MAX / 2 }, 
     529        { INT32_MIN / 2, INT32_MAX / 2 }, 
     530        { 0, TST_RAND_SAMPLE_RANGES - 1 }, 
     531        { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 } 
     532    }; 
     533    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS64Tests); iTest++) 
     534    { 
     535        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0}; 
     536        int64_t const  iFirst = s_aS64Tests[iTest].i64First; 
     537        int64_t const  iLast  = s_aS64Tests[iTest].i64Last; 
     538        uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest)); 
     539        uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1; 
    313540        RTPrintf("tstRand: TESTING RTRandS64Ex(%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange); 
    314541        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++) 
     
    323550    } 
    324551#endif 
     552#endif /* Testing RTRand */ 
     553 
     554#if 1 
     555    /* 
     556     * Test the various random generators. 
     557     */ 
     558    RTPrintf("tstRand: TESTING RTRandAdvCreateParkerMiller\n"); 
     559    RTRAND hRand; 
     560    int rc = RTRandAdvCreateParkMiller(&hRand); 
     561    CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); 
     562    if (RT_SUCCESS(rc)) 
     563        if (tstRandAdv(hRand)) 
     564            return 1; 
     565 
     566#endif /* Testing RTRandAdv */ 
    325567 
    326568    /* 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy