Files
2025-04-28 18:20:15 +02:00

102 lines
2.8 KiB
C++

#pragma once
#include <cstdint>
#include <algorithm>
#include <limits>
namespace wi::random
{
// deterministic random generator (xorshift64*):
// From: https://en.wikipedia.org/wiki/Xorshift
struct RNG
{
uint64_t state = 0;
constexpr RNG(uint64_t seed = 0) : state(seed) {}
// seeds the random number generator, seed should be non-zero number
constexpr void seed(uint64_t seed)
{
state = seed;
}
// gives an uint in range [0, UINT64_MAX]
constexpr uint64_t next_uint()
{
state ^= state >> 12ull;
state ^= state << 25ull;
state ^= state >> 27ull;
return state * 0x2545F4914F6CDD1DULL;
}
// gives an uint64 in range [min, max]
constexpr uint64_t next_uint(uint64_t min, uint64_t max)
{
if (min == max)
return min;
return min + (next_uint() % (std::min(std::numeric_limits<uint64_t>::max() - uint64_t(1), std::max(uint64_t(1), max - min)) + uint64_t(1)));
}
// gives an uint32 in range [min, max]
constexpr uint32_t next_uint(uint32_t min, uint32_t max)
{
if (min == max)
return min;
return min + (uint32_t(next_uint()) % (std::min(std::numeric_limits<uint32_t>::max() - uint32_t(1), std::max(uint32_t(1), max - min)) + uint32_t(1)));
}
// gives an int64 in range [-INT64_MAX, INT64_MAX]
constexpr int64_t next_int()
{
union
{
uint64_t u;
int64_t i;
} value = {};
value.u = next_uint();
return value.i;
}
// gives an int64 in range [min, max]
constexpr int64_t next_int(int64_t min, int64_t max)
{
if (min == max)
return min;
return min + int64_t(next_uint() % (std::min(std::numeric_limits<int64_t>::max() - int64_t(1), std::max(int64_t(1), max - min)) + int64_t(1))); // we roll next_uint here to avoid negative value messing with range mapping
}
// gives an int32 in range [min, max]
constexpr int32_t next_int(int32_t min, int32_t max)
{
if (min == max)
return min;
return min + int32_t(next_uint() % (std::min(std::numeric_limits<int32_t>::max() - int32_t(1), std::max(int32_t(1), max - min)) + int32_t(1))); // we roll next_uint here to avoid negative value messing with range mapping
}
// gives a float in range [0, 1]
constexpr float next_float()
{
union
{
uint32_t u;
float f;
} value = {};
value.u = 0x3f800000u | (uint32_t(next_uint()) >> 9);
return value.f - 1.0f;
}
// gives a float in range [min, max]
constexpr float next_float(float min, float max)
{
return min + (max - min) * next_float();
}
};
int GetRandom(int minValue, int maxValue);
int GetRandom(int maxValue);
uint32_t GetRandom(uint32_t minValue, uint32_t maxValue);
uint32_t GetRandom(uint32_t maxValue);
uint64_t GetRandom(uint64_t minValue, uint64_t maxValue);
uint64_t GetRandom(uint64_t maxValue);
float GetRandom(float minValue, float maxValue);
float GetRandom(float maxValue);
};