1
1
forked from 0ad/0ad
0ad/source/lib/rand.cpp
janwas 9d2acce9d8 # SwEng/cleanup
- 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.
2007-05-18 00:14:26 +00:00

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;
}