forked from staticvariablejames/CookieClickerCppTools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrandom.cpp
58 lines (48 loc) · 1.36 KB
/
random.cpp
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
#include "random.h"
namespace CCCPP {
rc4_engine::rc4_engine(const std::string& key):
i(0), j(0)
{
for(auto x = 0; x < rc4_engine::width; x++) {
S[x] = x;
}
auto y = 0;
for(auto x = 0; x < 256; x++) {
y = (y + S[x] + key[x % key.length()]) % rc4_engine::width;
std::swap(S[x], S[y]);
}
// Discard the first 256 values
for(auto x = 0; x < 256; x++) {
this->operator()();
}
}
auto rc4_engine::operator()() -> unsigned {
i = (i+1) % rc4_engine::width;
j = (j + S[i]) % rc4_engine::width;
std::swap(S[i], S[j]);
return S[(S[i] + S[j]) % rc4_engine::width];
}
auto generate_canonical(rc4_engine& e) -> double {
constexpr auto significance = 4503599627370496.0; // pow(2, 52)
auto n = 0.0, d = 1.0; // numerator and denominator
unsigned x = 0; // next bit to be added to the numerator
while(n < significance) {
n = (n + x) * rc4_engine::width;
d *= rc4_engine::width;
x = e();
}
while(n >= 2*significance) {
n /= 2;
d /= 2;
x >>= 1;
}
return (n+x)/d;
}
static const auto null_string = std::string{'\0'};
prng::prng(const std::string& key) :
engine(key == "" ? null_string : key) // Avoid binding temporary to a reference
{}
auto prng::operator()() -> double {
return generate_canonical(engine);
}
} // namespace CCCPP