#include "core/Random.hpp" #include using Core::Random; Random::Random(u32 seed) : data(), index(0) { for(u32& u : data) { u = seed; seed = seed * 7 + 31; } } void Random::update() { constexpr int M = 7; static const u32 map[2] = {0, 0x8EBF'D028}; for(size_t i = 0; i < data.getLength() - M; i++) { data[i] = data[i + M] ^ (data[i] >> 1) ^ map[data[i] & 1]; } for(size_t i = data.getLength() - M; i < data.getLength(); i++) { data[i] = data[i + (M - data.getLength())] ^ (data[i] >> 1) ^ map[data[i] & 1]; } index = 0; } u32 Random::nextU32() { if(index >= data.getLength()) { update(); } u32 u = data[index++]; u ^= (u << 7) & 0x2B5B'2500; u ^= (u << 15) & 0xDB8B'0000; u ^= (u >> 16); return u; } template T limit(T value, T min, T exclusiveMax) { return min + value % (exclusiveMax - min); } u32 Random::nextU32(u32 min, u32 exclusiveMax) { return limit(nextU32(), min, exclusiveMax); } i32 Random::nextI32(i32 min, i32 exclusiveMax) { return limit(static_cast(nextU32() >> 1), min, exclusiveMax); } size_t Core::Random::nextSize(size_t min, size_t exclusiveMax) { return limit(nextU32(), min, exclusiveMax); } bool Core::Random::nextBool() { return nextU32() & 1; } float Core::Random::nextFloat() { float f = static_cast(nextU32()) / static_cast(0xFFFF'FFFFu); return f >= 1.0f ? nextFloat() : f; }