#pragma once #include #include #include template class IRanGen { DECLARE_AS_INTERFACE(IRanGen) virtual T next() = 0; }; template class RanGenUniform : public IRanGen { private: std::random_device mRandomDevice; std::mt19937 mGen; using DISTRIBUTION = typename std::conditional< std::is_integral::value, std::uniform_int_distribution, std::uniform_real_distribution>::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 RanGenNormal : public IRanGen { private: std::random_device mRandomDevice; std::mt19937 mGen; using TYPE = typename std::conditional< std::is_floating_point::value, T, float>::type; using DISTRIBUTION = typename std::conditional< std::is_floating_point::value, std::normal_distribution, std::normal_distribution>::type; DISTRIBUTION mDistribution; public: RanGenNormal(TYPE mean, TYPE stddev) : mRandomDevice {}, mDistribution { mean, stddev }, mGen { mRandomDevice() } { } T next() override { if constexpr (std::is_integral::value) { return (T)std::lroundf(mDistribution(mGen)); } else { return mDistribution(mGen); } } };