1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
#include "Random.h"
#include <limits>
#include <random>
#include <cstdint>
#include "globalincs/pstypes.h"
namespace util {
namespace {
template <typename RngType>
class RandomImpl {
public:
void seed(const unsigned int val)
{
static_assert(RngType::min() == 0, "RNG min must be 0");
static_assert(RngType::max() == std::numeric_limits<uint32_t>::max(), "RNG max must be INT32_MAX");
// follow srand semantics
if (val == 1) {
m_rng.seed();
} else {
m_rng.seed(val);
}
}
int next()
{
return m_rng() & Random::MAX_VALUE;
}
void advance(unsigned long long distance)
{
m_rng.discard(distance);
}
private:
RngType m_rng;
};
RandomImpl<std::mt19937> SCP_rng;
} // namespace
Random::Random() = default;
void Random::seed(unsigned int val)
{
Assert(val > 0);
SCP_rng.seed(val);
}
int Random::next()
{
return SCP_rng.next();
}
int Random::next(int modulus)
{
Assert(modulus > 0);
return SCP_rng.next() % modulus;
}
int Random::next(int low, int high)
{
const int range = high - low + 1;
Assert(range > 0);
return low + (SCP_rng.next() % range);
}
bool Random::flip_coin()
{
// [0, HALF_MAX_VALUE] and [HALF_MAX_VALUE+1,MAX_VALUE] are the same size
return SCP_rng.next() <= Random::HALF_MAX_VALUE;
}
void Random::advance(unsigned long long distance)
{
SCP_rng.advance(distance);
}
} // namespace util
|