2026-01-26 18:56:53 +09:00

85 lines
1.9 KiB
C++

#pragma once
#include <random>
#include <type_traits>
#include <hermes/CommonDefs.h>
template <class T>
class IRanGen
{
DECLARE_AS_INTERFACE(IRanGen)
virtual T next() = 0;
};
template <class T = int>
class RanGenUniform : public IRanGen<T>
{
private:
std::random_device mRandomDevice;
std::mt19937 mGen;
using DISTRIBUTION = typename std::conditional<
std::is_integral<T>::value,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>>::type;
DISTRIBUTION mDistribution;
public:
RanGenUniform(T min, T max)
: mRandomDevice {},
mDistribution {
(std::min)(min, max),
(std::max)(min, max) },
mGen { mRandomDevice() }
{
}
T next() override
{
return mDistribution(mGen);
}
};
template <class T = float>
class RanGenNormal : public IRanGen<T>
{
private:
std::random_device mRandomDevice;
std::mt19937 mGen;
using TYPE = typename std::conditional<
std::is_floating_point<T>::value,
T,
float>::type;
using DISTRIBUTION = typename std::conditional<
std::is_floating_point<T>::value,
std::normal_distribution<T>,
std::normal_distribution<TYPE>>::type;
DISTRIBUTION mDistribution;
public:
RanGenNormal(TYPE mean, TYPE stddev)
: mRandomDevice {},
mDistribution { mean, stddev },
mGen { mRandomDevice() }
{
}
T next() override
{
if constexpr (std::is_integral<T>::value) {
return (T)std::lroundf(mDistribution(mGen));
} else {
return mDistribution(mGen);
}
}
};