5#ifndef LINE_UTIL_RNG_SSJ_H
6#define LINE_UTIL_RNG_SSJ_H
82 : z_(static_cast<std::uint64_t>(seed) * kGolden ^ static_cast<std::uint64_t>(offset)) {}
88 x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ULL;
89 x = (x ^ (x >> 27)) * 0x94D049BB133111EBULL;
98 for (
int i = 0; i < 6; ++i) {
99 const std::uint64_t m = (i < 3) ? 4294967087ULL : 4294944443ULL;
100 s[i] =
static_cast<long long>(1 +
next() % (m - 1));
105 static constexpr std::uint64_t kGolden = 0x9E3779B97F4A7C15ULL;
127 for (
int i = 0; i < 6; ++i) cg_[i] = static_cast<double>(s[i]);
133 SeedHash(seed, offset).mrg_seeds(s);
143 double p1 = kA12 * cg_[1] - kA13n * cg_[0];
144 double k = std::floor(p1 / kM1);
146 if (p1 < 0.0) p1 += kM1;
152 double p2 = kA21 * cg_[5] - kA23n * cg_[3];
153 k = std::floor(p2 / kM2);
155 if (p2 < 0.0) p2 += kM2;
161 return ((p1 > p2) ? (p1 - p2) * kNorm : (p1 - p2 + kM1) * kNorm);
166 if (i > j)
throw InputError(
"Mrg32k3a::next_int: empty range");
167 return i +
static_cast<int>(
next_double() * (
static_cast<double>(j - i) + 1.0));
171 double state(
int i)
const {
return cg_[i]; }
174 void reset_to_default() {
176 for (
int i = 0; i < 6; ++i) cg_[i] = 12345.0;
179 static void validate(
const long long s[6]) {
180 for (
int i = 0; i < 3; ++i) {
181 if (s[i] < 0 ||
static_cast<double>(s[i]) >= kM1)
182 throw InputError(
"Mrg32k3a::set_seed: the first three seeds must be in [0, m1)");
184 for (
int i = 3; i < 6; ++i) {
185 if (s[i] < 0 ||
static_cast<double>(s[i]) >= kM2)
186 throw InputError(
"Mrg32k3a::set_seed: the last three seeds must be in [0, m2)");
188 if (s[0] == 0 && s[1] == 0 && s[2] == 0)
189 throw InputError(
"Mrg32k3a::set_seed: the first three seeds must not all be zero");
190 if (s[3] == 0 && s[4] == 0 && s[5] == 0)
191 throw InputError(
"Mrg32k3a::set_seed: the last three seeds must not all be zero");
195 static constexpr double kM1 = 4294967087.0;
196 static constexpr double kM2 = 4294944443.0;
197 static constexpr double kA12 = 1403580.0;
198 static constexpr double kA13n = 810728.0;
199 static constexpr double kA21 = 527612.0;
200 static constexpr double kA23n = 1370589.0;
202 static constexpr double kNorm = 2.328306549295727688e-10;
225 seed_ = (
static_cast<uint64_t
>(seed) ^ 0x5DEECE66DULL) & ((1ULL << 48) - 1);
226 have_next_gaussian_ =
false;
231 seed_ = (seed_ * 0x5DEECE66DULL + 0xBULL) & ((1ULL << 48) - 1);
232 return static_cast<int32_t
>(
static_cast<int64_t
>(seed_) >> (48 - bits));
240 if (bound <= 0)
throw InputError(
"JavaRandom::next_int: bound must be positive");
241 if ((bound & -bound) == bound) {
242 return static_cast<int32_t
>((
static_cast<int64_t
>(bound) *
next(31)) >> 31);
248 }
while (bits - val + (bound - 1) < 0);
254 return static_cast<double>((
static_cast<int64_t
>(
next(26)) << 27) +
next(27)) /
255 static_cast<double>(1LL << 53);
260 return (
static_cast<int64_t
>(
next(32)) << 32) +
next(32);
268 if (have_next_gaussian_) {
269 have_next_gaussian_ =
false;
270 return next_gaussian_;
276 s = v1 * v1 + v2 * v2;
277 }
while (s >= 1.0 || s == 0.0);
278 const double multiplier = std::sqrt(-2.0 * std::log(s) / s);
279 next_gaussian_ = v2 * multiplier;
280 have_next_gaussian_ =
true;
281 return v1 * multiplier;
286 bool have_next_gaussian_ =
false;
287 double next_gaussian_ = 0.0;
JavaRandom(long long seed=0)
bool next_boolean()
Java's nextBoolean().
int32_t next(int bits)
Java's next(bits).
void set_seed(long long seed)
Java's setSeed: scramble by 0x5DEECE66D and mask to 48 bits.
double next_gaussian()
Java's nextGaussian(), the polar method with its cached second value.
int32_t next_int(int32_t bound)
Java's nextInt(bound), including the rejection loop it documents.
double next_double()
Java's nextDouble(): a 26-bit and a 27-bit draw.
int64_t next_long()
Java's nextLong().
int32_t next_int()
Java's nextInt().
void set_seed(const long long s[6])
SSJ's setSeed(long[6]).
int next_int(int i, int j)
SSJ's nextInt(i, j): a uniform integer on [i, j].
double next_double()
SSJ's nextValue(): the combined generator, returning a double in (0, 1).
double state(int i) const
The six state doubles, for tests that pin the state and not only the draws.
void set_seed_offset(long long seed, long long offset)
The stream an LDES engine names by (run seed, offset): its seeds hashed by SeedHash.
std::uint64_t next()
The next splitmix64 output.
void mrg_seeds(long long s[6])
Six MRG32k3a seeds: the first three in [1, m1), the last three in [1, m2), so neither component can s...
SeedHash(long long seed, long long offset)
The exception types the port throws.
Conservation laws of a layered queueing network, enumerated from its structure.