Files
TSE/TSE_Math/src/Random.cpp

108 lines
3.2 KiB
C++

#include "Random.hpp"
#include <bit>
#include <cstdint>
TSE::Random::Random(uint seed)
{
state = static_cast<uint>(static_cast<std::uint32_t>(seed));
}
TSE::uint TSE::Random::nextUInt(uint minInc, uint maxInc)
{
constexpr std::uint32_t multiplier = 1664525u;
constexpr std::uint32_t increment = 1013904223u;
std::uint32_t nextState = static_cast<std::uint32_t>(state);
nextState = nextState * multiplier + increment;
state = static_cast<uint>(nextState);
if(minInc == 0u && maxInc == 0u)
{
return state;
}
if(minInc > maxInc)
{
uint temp = minInc;
minInc = maxInc;
maxInc = temp;
}
const std::uint64_t span = static_cast<std::uint64_t>(maxInc) - static_cast<std::uint64_t>(minInc) + 1ull;
const std::uint64_t offset = static_cast<std::uint64_t>(nextState) % span;
return static_cast<uint>(static_cast<std::uint64_t>(minInc) + offset);
}
int TSE::Random::nextInt(int minInc, int maxInc)
{
const std::uint32_t bits = static_cast<std::uint32_t>(nextUInt());
if(minInc == 0 && maxInc == 0)
{
return static_cast<int>(std::bit_cast<std::int32_t>(bits));
}
if(minInc > maxInc)
{
int temp = minInc;
minInc = maxInc;
maxInc = temp;
}
const std::int64_t span = static_cast<std::int64_t>(maxInc) - static_cast<std::int64_t>(minInc) + 1ll;
const std::uint64_t offset = static_cast<std::uint64_t>(bits) % static_cast<std::uint64_t>(span);
const std::int64_t value = static_cast<std::int64_t>(minInc) + static_cast<std::int64_t>(offset);
return static_cast<int>(value);
}
short TSE::Random::nextShort(short minInc, short maxInc)
{
const std::uint32_t bits = static_cast<std::uint32_t>(nextUInt());
const std::uint16_t lowerBits = static_cast<std::uint16_t>(bits);
if(minInc == 0 && maxInc == 0)
{
return static_cast<short>(std::bit_cast<std::int16_t>(lowerBits));
}
if(minInc > maxInc)
{
short temp = minInc;
minInc = maxInc;
maxInc = temp;
}
const std::int32_t span = static_cast<std::int32_t>(maxInc) - static_cast<std::int32_t>(minInc) + 1;
const std::uint32_t offset = static_cast<std::uint32_t>(lowerBits) % static_cast<std::uint32_t>(span);
const std::int32_t value = static_cast<std::int32_t>(minInc) + static_cast<std::int32_t>(offset);
return static_cast<short>(value);
}
TSE::byte TSE::Random::nextByte(byte minInc, byte maxInc)
{
const std::uint32_t bits = static_cast<std::uint32_t>(nextUInt());
const std::uint8_t lowerBits = static_cast<std::uint8_t>(bits);
if(minInc == 0 && maxInc == 0)
{
return static_cast<byte>(lowerBits);
}
if(minInc > maxInc)
{
byte temp = minInc;
minInc = maxInc;
maxInc = temp;
}
const std::uint16_t span = static_cast<std::uint16_t>(maxInc) - static_cast<std::uint16_t>(minInc) + 1u;
const std::uint16_t offset = static_cast<std::uint16_t>(lowerBits) % span;
return static_cast<byte>(static_cast<std::uint16_t>(minInc) + offset);
}
float TSE::Random::nextFloat01()
{
constexpr float invRange = 1.0f / 4294967296.0f;
return static_cast<float>(static_cast<std::uint32_t>(nextUInt())) * invRange;
}