[*] 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
This commit is contained in:
Reece Wilson 2023-11-15 17:53:37 +00:00
parent e3cecc2d35
commit 999f3e69ca
3 changed files with 100 additions and 23 deletions

View File

@ -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<false>(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<AuUInt8>();
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<AuUInt32>();
if (this->def_.bSecure)
{
AuUInt32 uRet {};
ReadSecureRNG({ &uRet, 4 });
return uRet;
}
else
{
return WELL_NextLong(&this->fast_);
}
}
AuUInt64 RandomDevice::NextU64()
{
if (this->def_.bSecure)
{
AuUInt64 uRet {};
ReadSecureRNG({ &uRet, 8 });
return uRet;
}
else
{
return NextFillTmpl<AuUInt64>();
}
}
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<AuUInt32>(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<AuUInt32>(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<AuUInt32>(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()

View File

@ -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<AuUInt8, 64> &seed)
WELLRand &&WELL_SeedRandBig64(const AuArray<AuUInt8, 64> &seed)
{
WELLRand rand {};
static_assert(64 == sizeof(rand.state));
AuMemcpy(rand.state, seed.data(), sizeof(rand.state));
return rand;
return AuMove(rand);
}
/**

View File

@ -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<AuUInt8, 64> &seed);
WELLRand WELL_SeedRand64(AuUInt64 seed);
WELLRand &&WELL_SeedRand(AuUInt32 seed);
WELLRand &&WELL_SeedRandBig64(const AuArray<AuUInt8, 64> &seed);
WELLRand &&WELL_SeedRand64(AuUInt64 seed);
AuUInt32 WELL_NextLong(WELLRand* rand);
void WELL_NextBytes(WELLRand *rand, void *in, AuUInt32 length);