Newer
Older
/*
This file is part of Leela Zero.
Copyright (C) 2017 Gian-Carlo Pascutto
Leela Zero is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Leela Zero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Leela Zero. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Random.h"
#include <climits>
#include <cstdint>
#include <thread>
#include <random>
#include "Utils.hpp"
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
namespace Utils
{
Random& Random::get_Rng(void) {
static thread_local Random s_rng{0};
return s_rng;
}
Random::Random(std::uint64_t seed) {
if (seed == 0) {
size_t thread_id =
std::hash<std::thread::id>()(std::this_thread::get_id());
seedrandom((std::uint64_t)thread_id);
} else {
seedrandom(seed);
}
}
// This is xoroshiro128+.
// Note that the last bit isn't entirely random, so don't use it,
// if possible.
std::uint64_t Random::gen(void) {
const std::uint64_t s0 = m_s[0];
std::uint64_t s1 = m_s[1];
const std::uint64_t result = s0 + s1;
s1 ^= s0;
m_s[0] = Utils::rotl(s0, 55) ^ s1 ^ (s1 << 14);
m_s[1] = Utils::rotl(s1, 36);
return result;
}
std::uint64_t Random::randuint64(const uint64_t max) {
const uint64_t inclusive_max = max - 1;
return std::uniform_int_distribution<uint64_t>{0, inclusive_max}(*this);
}
std::uint64_t Random::randuint64() {
return gen();
}
static std::uint64_t splitmix64(std::uint64_t z) {
z += 0x9e3779b97f4a7c15;
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
void Random::seedrandom(std::uint64_t seed) {
// Initialize state of xoroshiro128+ by transforming the seed
// with the splitmix64 algorithm.
// As suggested by http://xoroshiro.di.unimi.it/xoroshiro128plus.c
m_s[0] = splitmix64(seed);
m_s[1] = splitmix64(m_s[0]);
}
}