File: Random.cpp

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (83 lines) | stat: -rw-r--r-- 1,352 bytes parent folder | download | duplicates (2)
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