janwas
9d2acce9d8
- deleted most old libraries/headers in codepit to avoid confusion (they are now in SVN anyway). updated required-libraries-linux.txt accordingly - moved rand() into separate file, out of lib.cpp - removed CGUIScrollBarStyle.cpp to avoid empty-file warning - wxwidgets.h: remove redundant #pragma lib and include wxw PCH - move openal-specific stuff to external_libraries/openal.h - cpu, bsd: macosx is-a bsd, so only test OS_BSD This was SVN commit r5082.
63 lines
1.7 KiB
C++
63 lines
1.7 KiB
C++
/**
|
|
* =========================================================================
|
|
* File : rand.cpp
|
|
* Project : 0 A.D.
|
|
* Description : pseudorandom number generator
|
|
* =========================================================================
|
|
*/
|
|
|
|
// license: GPL; see lib/license.txt
|
|
|
|
#include "precompiled.h"
|
|
#include "rand.h"
|
|
|
|
// avoids several common pitfalls; see discussion at
|
|
// http://www.azillionmonkeys.com/qed/random.html
|
|
|
|
// rand() is poorly implemented (e.g. in VC7) and only returns < 16 bits;
|
|
// double that amount by concatenating 2 random numbers.
|
|
// this is not to fix poor rand() randomness - the number returned will be
|
|
// folded down to a much smaller interval anyway. instead, a larger XRAND_MAX
|
|
// decreases the probability of having to repeat the loop.
|
|
#if RAND_MAX < 65536
|
|
static const uint XRAND_MAX = (RAND_MAX+1)*(RAND_MAX+1) - 1;
|
|
static uint xrand()
|
|
{
|
|
return rand()*(RAND_MAX+1) + rand();
|
|
}
|
|
// rand() is already ok; no need to do anything.
|
|
#else
|
|
static const uint XRAND_MAX = RAND_MAX;
|
|
static uint xrand()
|
|
{
|
|
return rand();
|
|
}
|
|
#endif
|
|
|
|
uint rand(uint min_inclusive, uint max_exclusive)
|
|
{
|
|
const uint range = (max_exclusive-min_inclusive);
|
|
// huge interval or min >= max
|
|
if(range == 0 || range > XRAND_MAX)
|
|
{
|
|
WARN_ERR(ERR::INVALID_PARAM);
|
|
return 0;
|
|
}
|
|
|
|
const uint inv_range = XRAND_MAX / range;
|
|
|
|
// generate random number in [0, range)
|
|
// idea: avoid skewed distributions when <range> doesn't evenly divide
|
|
// XRAND_MAX by simply discarding values in the "remainder".
|
|
// not expected to run often since XRAND_MAX is large.
|
|
uint x;
|
|
do
|
|
x = xrand();
|
|
while(x >= range * inv_range);
|
|
x /= inv_range;
|
|
|
|
x += min_inclusive;
|
|
debug_assert(x < max_exclusive);
|
|
return x;
|
|
}
|