forked from Fluorohydride/ygopro-core
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmtrandom.h
More file actions
105 lines (91 loc) · 2.24 KB
/
mtrandom.h
File metadata and controls
105 lines (91 loc) · 2.24 KB
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
* mtrandom.h
*
* Created on: 2009-10-18
* Author: Argon.Sun
*/
#ifndef MTRANDOM_H_
#define MTRANDOM_H_
#include <random>
#include <vector>
#include <utility>
class mtrandom {
public:
const unsigned int rand_max{ std::mt19937::max() };
mtrandom() :
rng() {}
mtrandom(uint32_t seq[], size_t len) {
std::seed_seq q(seq, seq + len);
rng.seed(q);
}
explicit mtrandom(uint_fast32_t value) :
rng(value) {}
mtrandom(std::seed_seq& q) :
rng(q) {}
mtrandom(const mtrandom& other) = delete;
void operator=(const mtrandom& other) = delete;
// mersenne_twister_engine
void seed(uint32_t seq[], size_t len) {
std::seed_seq q(seq, seq + len);
rng.seed(q);
}
void seed(uint_fast32_t value) {
rng.seed(value);
}
void seed(std::seed_seq& q) {
rng.seed(q);
}
uint_fast32_t rand() {
return rng();
}
void discard(unsigned long long z) {
rng.discard(z);
}
// old vesion, discard too many numbers
int get_random_integer_v1(int l, int h) {
uint32_t range = (h - l + 1);
uint32_t secureMax = rand_max - rand_max % range;
uint_fast32_t x;
do {
x = rng();
} while (x >= secureMax);
return l + (int)(x % range);
}
#pragma warning(disable:4146)
// N % k = (N - k) % k = (-k) % k
// discard (N % range) numbers from the left end so that it is a multiple of range
int get_random_integer_v2(int l, int h) {
uint32_t range = (h - l + 1);
uint32_t bound = -range % range;
auto x = rng();
while (x < bound) {
x = rng();
}
return l + (int)(x % range);
}
#pragma warning(default:4146)
// Fisher-Yates shuffle [first, last)
template<typename T>
void shuffle_vector(std::vector<T>& v, int first, int last, int version) {
if ((size_t)last > v.size())
last = (int)v.size();
auto distribution = &mtrandom::get_random_integer_v2;
if (version == 1)
distribution = &mtrandom::get_random_integer_v1;
for (int i = first; i < last - 1; ++i) {
int r = (this->*distribution)(i, last - 1);
std::swap(v[i], v[r]);
}
}
template<typename T>
void shuffle_vector(std::vector<T>& v) {
shuffle_vector(v, 0, (int)v.size(), 2);
}
template<typename T>
void shuffle_vector(std::vector<T>& v, int first, int last) {
shuffle_vector(v, first, last, 2);
}
private:
std::mt19937 rng;
};
#endif /* MTRANDOM_H_ */