From 73bc3d8ea49a4793b14976e86010a36f19c1d18b Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 9 Nov 2019 13:32:58 +0100 Subject: Core/Random: Refactor random number generation to use std::uniform_*_distribution to restrict result range instead of doing that ourselves * Seed SFMTRand with more values for its state --- src/common/Utilities/SFMTRand.cpp | 75 ++++++++++----------------------------- 1 file changed, 19 insertions(+), 56 deletions(-) (limited to 'src/common/Utilities/SFMTRand.cpp') diff --git a/src/common/Utilities/SFMTRand.cpp b/src/common/Utilities/SFMTRand.cpp index ca88ad88559..c3eb947e9e5 100644 --- a/src/common/Utilities/SFMTRand.cpp +++ b/src/common/Utilities/SFMTRand.cpp @@ -16,67 +16,30 @@ */ #include "SFMTRand.h" - -#include +#include +#include +#include +#include #include #include SFMTRand::SFMTRand() { - RandomInit((uint32_t)(time(0))); -} - -void SFMTRand::RandomInit(uint32_t seed) // Re-seed -{ - sfmt_init_gen_rand(&state, seed); -} - -int32_t SFMTRand::IRandom(int32_t min, int32_t max) // Output random integer -{ - // Output random integer in the interval min <= x <= max - // Slightly inaccurate if (max-min+1) is not a power of 2 - if (max <= min) { - if (max == min) return min; else return 0x80000000; - } - // Assume 64 bit integers supported. Use multiply and shift method - uint32_t interval; // Length of interval - uint64_t longran; // Random bits * interval - uint32_t iran; // Longran / 2^32 + std::random_device dev; + if (dev.entropy() > 0) + { + std::array seed; + std::generate(seed.begin(), seed.end(), std::ref(dev)); - interval = (uint32_t)(max - min + 1); - longran = (uint64_t)BRandom() * interval; - iran = (uint32_t)(longran >> 32); - // Convert back to signed and return result - return (int32_t)iran + min; -} - -uint32_t SFMTRand::URandom(uint32_t min, uint32_t max) -{ - // Output random integer in the interval min <= x <= max - // Slightly inaccurate if (max-min+1) is not a power of 2 - if (max <= min) { - if (max == min) return min; else return 0; + sfmt_init_by_array(&_state, seed.data(), seed.size()); } - // Assume 64 bit integers supported. Use multiply and shift method - uint32_t interval; // Length of interval - uint64_t longran; // Random bits * interval - uint32_t iran; // Longran / 2^32 - - interval = (uint32_t)(max - min + 1); - longran = (uint64_t)BRandom() * interval; - iran = (uint32_t)(longran >> 32); - // Convert back to signed and return result - return iran + min; + else + sfmt_init_gen_rand(&_state, uint32(time(nullptr))); } -double SFMTRand::Random() // Output random floating point number +uint32 SFMTRand::RandomUInt32() // Output random bits { - return sfmt_genrand_real1(&state); -} - -uint32_t SFMTRand::BRandom() // Output random bits -{ - return sfmt_genrand_uint32(&state); + return sfmt_genrand_uint32(&_state); } void* SFMTRand::operator new(size_t size, std::nothrow_t const&) @@ -84,7 +47,7 @@ void* SFMTRand::operator new(size_t size, std::nothrow_t const&) return _mm_malloc(size, 16); } - void SFMTRand::operator delete(void* ptr, std::nothrow_t const&) +void SFMTRand::operator delete(void* ptr, std::nothrow_t const&) { _mm_free(ptr); } @@ -104,17 +67,17 @@ void* SFMTRand::operator new[](size_t size, std::nothrow_t const&) return _mm_malloc(size, 16); } - void SFMTRand::operator delete[](void* ptr, std::nothrow_t const&) +void SFMTRand::operator delete[](void* ptr, std::nothrow_t const&) { _mm_free(ptr); } - void* SFMTRand::operator new[](size_t size) +void* SFMTRand::operator new[](size_t size) { return _mm_malloc(size, 16); } - void SFMTRand::operator delete[](void* ptr) +void SFMTRand::operator delete[](void* ptr) { _mm_free(ptr); -} \ No newline at end of file +} -- cgit v1.2.3