diff --git a/Source/RNG/AuRandomDevice.cpp b/Source/RNG/AuRandomDevice.cpp index 64ecfa33..53ec4909 100644 --- a/Source/RNG/AuRandomDevice.cpp +++ b/Source/RNG/AuRandomDevice.cpp @@ -72,6 +72,13 @@ namespace Aurora::RNG return ret; } + static AuUInt64 RngConvertBounds(AuUInt32 i) + { + AuUInt8 ret; + AuBitScanReverse(ret, i); + return 1ull << (ret + 1); + } + void RandomDevice::NextString(char *pString, AuUInt32 uLength, ERngStringCharacters type) { static AuPair rngSequence[static_cast(ERngStringCharacters::eEnumCount)] = @@ -81,7 +88,7 @@ namespace Aurora::RNG {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26}, {"1234567890", 10}, {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62}, - {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!!$%^*.[];:", 76} + {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!$%^*.[];:", 75} }; if (!pString) @@ -102,7 +109,14 @@ namespace Aurora::RNG for (auto i = 0u; i < uLength; i++) { - pString[i] = pair.first[reinterpret_cast(pString)[i] % static_cast(pair.second)]; + auto uUpperBound = RngConvertBounds(pair.second); + AuUInt8 uNext {}; + auto uWord = reinterpret_cast(pString)[i]; + while ((uNext = (uWord & (uUpperBound - 1))) >= pair.second) + { + uWord = AuFnv1a32Runtime(&uWord, sizeof(uWord)); + } + pString[i] = pair.first[uNext]; } } @@ -170,11 +184,11 @@ namespace Aurora::RNG #else auto uRange = uMax - uMin; auto uMassiveWord = NextU32(); - auto uUpperBound = AuPageRoundUp(uRange, 2); + auto uUpperBound = RngConvertBounds(uRange + 1); AuUInt32 uNext {}; while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange) { - uMassiveWord = NextU32(); + uMassiveWord = AuFnv1a32Runtime(&uMassiveWord, sizeof(uMassiveWord)); } return uMin + uNext; #endif @@ -188,11 +202,11 @@ namespace Aurora::RNG #else auto uRange = uMax - uMin; auto uMassiveWord = NextU32(); - auto uUpperBound = AuPageRoundUp(uRange, 2); + auto uUpperBound = RngConvertBounds(uRange + 1); AuUInt32 uNext {}; while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange) { - uMassiveWord = NextU32(); + uMassiveWord = AuFnv1a32Runtime(&uMassiveWord, sizeof(uMassiveWord)); } return uMin + uNext; #endif @@ -209,11 +223,11 @@ namespace Aurora::RNG return NextU32() % uCount; #else auto uMassiveWord = NextU32(); - auto uUpperBound = AuPageRoundUp(uCount, 2); + auto uUpperBound = RngConvertBounds(uCount); AuUInt32 uNext {}; while ((uNext = (uMassiveWord & (uUpperBound - 1))) >= uCount) { - uMassiveWord = NextU32(); + uMassiveWord = AuFnv1a32Runtime(&uMassiveWord, sizeof(uMassiveWord)); } return uNext; #endif