From 999f3e69ca58f41e172640617dee1378c5a8fff1 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Wed, 15 Nov 2023 17:53:37 +0000 Subject: [PATCH] [*] RNG (PLAYBACK ABI-BREAK!!!): preemptively silence the turbo autists that are going to complain about modulo bias (...well, mostly. this will be good enough.) [*] Improve fast RNG device perf --- Source/RNG/AuRandomDevice.cpp | 94 ++++++++++++++++++++++++++++++----- Source/RNG/AuWELL.cpp | 12 ++--- Source/RNG/AuWELL.hpp | 17 +++++-- 3 files changed, 100 insertions(+), 23 deletions(-) diff --git a/Source/RNG/AuRandomDevice.cpp b/Source/RNG/AuRandomDevice.cpp index 6c946916..dec52c12 100644 --- a/Source/RNG/AuRandomDevice.cpp +++ b/Source/RNG/AuRandomDevice.cpp @@ -29,19 +29,18 @@ namespace Aurora::RNG { if (def.seed) { - this->fast_ = WELL_SeedRand(def.seed.value()); + this->fast_ = AuMove(WELL_SeedRand(def.seed.value())); } else if (def.seed64) { - this->fast_ = WELL_SeedRand64(def.seed64.value()); + this->fast_ = AuMove(WELL_SeedRand64(def.seed64.value())); } else if (def.seedMassive) { - this->fast_ = WELL_SeedRandBig64(def.seedMassive.value()); + this->fast_ = AuMove(WELL_SeedRandBig64(def.seedMassive.value())); } else { - this->fast_ = {}; RNG::RngFillArray(this->fast_.state); } } @@ -82,7 +81,7 @@ namespace Aurora::RNG {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26}, {"1234567890", 10}, {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62}, - {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!$%^*.[];:", 75} + {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!!$%^*.[];:", 76} }; if (!pString) @@ -109,34 +108,94 @@ namespace Aurora::RNG AuUInt8 RandomDevice::NextByte() { - return NextFillTmpl(); + if (this->def_.bSecure) + { + AuUInt8 uRet {}; + ReadSecureRNG({ &uRet, 1 }); + return uRet; + } + else + { + return AuUInt8(WELL_NextLong(&this->fast_) & 0xFF); + } } bool RandomDevice::NextBoolean() { - return NextByte() > 127; + if (this->def_.bSecure) + { + AuUInt8 uRet {}; + ReadSecureRNG({ &uRet, 1 }); + return bool(uRet & 0x1); + } + else + { + return bool(WELL_NextLong(&this->fast_) & 0x1); + } } AuUInt32 RandomDevice::NextU32() { - return NextFillTmpl(); + if (this->def_.bSecure) + { + AuUInt32 uRet {}; + ReadSecureRNG({ &uRet, 4 }); + return uRet; + } + else + { + return WELL_NextLong(&this->fast_); + } } AuUInt64 RandomDevice::NextU64() { - return NextFillTmpl(); + if (this->def_.bSecure) + { + AuUInt64 uRet {}; + ReadSecureRNG({ &uRet, 8 }); + return uRet; + } + else + { + return NextFillTmpl(); + } } AuInt32 RandomDevice::NextInt(AuInt32 uMin, AuInt32 uMax) { + #if 0 auto range = uMax - uMin; return (NextU64() % range) + uMin; + #else + auto uRange = uMax - uMin; + auto uMassiveWord = NextU32(); + auto uUpperBound = AuPageRoundUp(uRange, 2); + AuUInt32 uNext {}; + while ((uNext = (uMassiveWord & (uUpperBound - 1))) >= uRange) + { + uMassiveWord = NextU32(); + } + return uMin + uNext; + #endif } AuUInt32 RandomDevice::NextU32(AuUInt32 uMin, AuUInt32 uMax) { + #if 0 auto range = uMax - uMin; return (NextU64() % range) + uMin; + #else + auto uRange = uMax - uMin; + auto uMassiveWord = NextU32(); + auto uUpperBound = AuPageRoundUp(uRange, 2); + AuUInt32 uNext {}; + while ((uNext = (uMassiveWord & (uUpperBound - 1))) >= uRange) + { + uMassiveWord = NextU32(); + } + return uMin + uNext; + #endif } double RandomDevice::NextDecimal() @@ -146,13 +205,24 @@ namespace Aurora::RNG AuUInt32 RandomDevice::NextIndex(AuUInt32 uCount /* = max + 1*/) { + #if 0 return NextU32() % uCount; + #else + auto uMassiveWord = NextU32(); + auto uUpperBound = AuPageRoundUp(uCount, 2); + AuUInt32 uNext {}; + while ((uNext = (uMassiveWord & (uUpperBound - 1))) >= uCount) + { + uMassiveWord = NextU32(); + } + return uNext; + #endif } - float RandomDevice::NextNumber(float min, float max) + float RandomDevice::NextNumber(float fMin, float fMax) { - auto range = max - min; - return NextDecimal() * range + min; + auto fRange = fMax - fMin; + return NextDecimal() * fRange + fMin; } AuMemoryViewRead RandomDevice::ToSeed() diff --git a/Source/RNG/AuWELL.cpp b/Source/RNG/AuWELL.cpp index 9be0c123..e6824d0c 100644 --- a/Source/RNG/AuWELL.cpp +++ b/Source/RNG/AuWELL.cpp @@ -49,26 +49,26 @@ static auline void WELL_SeedRand(WELLRand *rand, AuUInt32 seed) /** * Creates a new random number generator from a given seed. */ -WELLRand WELL_SeedRand(AuUInt32 seed) +WELLRand &&WELL_SeedRand(AuUInt32 seed) { WELLRand rand {}; WELL_SeedRand(&rand, seed); - return rand; + return AuMove(rand); } -WELLRand WELL_SeedRand64(AuUInt64 seed) +WELLRand &&WELL_SeedRand64(AuUInt64 seed) { WELLRand rand {}; WELL_SeedRand64(&rand, seed); - return rand; + return AuMove(rand); } -WELLRand WELL_SeedRandBig64(const AuArray &seed) +WELLRand &&WELL_SeedRandBig64(const AuArray &seed) { WELLRand rand {}; static_assert(64 == sizeof(rand.state)); AuMemcpy(rand.state, seed.data(), sizeof(rand.state)); - return rand; + return AuMove(rand); } /** diff --git a/Source/RNG/AuWELL.hpp b/Source/RNG/AuWELL.hpp index 58f1db3a..e2698a9e 100644 --- a/Source/RNG/AuWELL.hpp +++ b/Source/RNG/AuWELL.hpp @@ -3,12 +3,19 @@ struct WELLRand { AuUInt32 state[16]; - int index; - AuThreadPrimitives::SpinLock lock; + int index {}; + AuFutexMutex lock; + + inline WELLRand &operator =(WELLRand &&rand) + { + AuMemcpy(this->state, rand.state, sizeof(this->state)); + this->index = rand.index; + return *this; + } }; -WELLRand WELL_SeedRand(AuUInt32 seed); -WELLRand WELL_SeedRandBig64(const AuArray &seed); -WELLRand WELL_SeedRand64(AuUInt64 seed); +WELLRand &&WELL_SeedRand(AuUInt32 seed); +WELLRand &&WELL_SeedRandBig64(const AuArray &seed); +WELLRand &&WELL_SeedRand64(AuUInt64 seed); AuUInt32 WELL_NextLong(WELLRand* rand); void WELL_NextBytes(WELLRand *rand, void *in, AuUInt32 length); \ No newline at end of file