[*] 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) if (def.seed)
{ {
this->fast_ = WELL_SeedRand(def.seed.value()); this->fast_ = AuMove(WELL_SeedRand(def.seed.value()));
} }
else if (def.seed64) else if (def.seed64)
{ {
this->fast_ = WELL_SeedRand64(def.seed64.value()); this->fast_ = AuMove(WELL_SeedRand64(def.seed64.value()));
} }
else if (def.seedMassive) else if (def.seedMassive)
{ {
this->fast_ = WELL_SeedRandBig64(def.seedMassive.value()); this->fast_ = AuMove(WELL_SeedRandBig64(def.seedMassive.value()));
} }
else else
{ {
this->fast_ = {};
RNG::RngFillArray<false>(this->fast_.state); RNG::RngFillArray<false>(this->fast_.state);
} }
} }
@ -82,7 +81,7 @@ namespace Aurora::RNG
{"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26}, {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26},
{"1234567890", 10}, {"1234567890", 10},
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62}, {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62},
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!$%^*.[];:", 75} {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!!$%^*.[];:", 76}
}; };
if (!pString) if (!pString)
@ -109,34 +108,94 @@ namespace Aurora::RNG
AuUInt8 RandomDevice::NextByte() 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() 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() 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() AuUInt64 RandomDevice::NextU64()
{ {
return NextFillTmpl<AuUInt64>(); if (this->def_.bSecure)
{
AuUInt64 uRet {};
ReadSecureRNG({ &uRet, 8 });
return uRet;
}
else
{
return NextFillTmpl<AuUInt64>();
}
} }
AuInt32 RandomDevice::NextInt(AuInt32 uMin, AuInt32 uMax) AuInt32 RandomDevice::NextInt(AuInt32 uMin, AuInt32 uMax)
{ {
#if 0
auto range = uMax - uMin; auto range = uMax - uMin;
return (NextU64() % range) + 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) AuUInt32 RandomDevice::NextU32(AuUInt32 uMin, AuUInt32 uMax)
{ {
#if 0
auto range = uMax - uMin; auto range = uMax - uMin;
return (NextU64() % range) + 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() double RandomDevice::NextDecimal()
@ -146,13 +205,24 @@ namespace Aurora::RNG
AuUInt32 RandomDevice::NextIndex(AuUInt32 uCount /* = max + 1*/) AuUInt32 RandomDevice::NextIndex(AuUInt32 uCount /* = max + 1*/)
{ {
#if 0
return NextU32() % uCount; 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; auto fRange = fMax - fMin;
return NextDecimal() * range + min; return NextDecimal() * fRange + fMin;
} }
AuMemoryViewRead RandomDevice::ToSeed() 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. * Creates a new random number generator from a given seed.
*/ */
WELLRand WELL_SeedRand(AuUInt32 seed) WELLRand &&WELL_SeedRand(AuUInt32 seed)
{ {
WELLRand rand {}; WELLRand rand {};
WELL_SeedRand(&rand, seed); WELL_SeedRand(&rand, seed);
return rand; return AuMove(rand);
} }
WELLRand WELL_SeedRand64(AuUInt64 seed) WELLRand &&WELL_SeedRand64(AuUInt64 seed)
{ {
WELLRand rand {}; WELLRand rand {};
WELL_SeedRand64(&rand, seed); 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 {}; WELLRand rand {};
static_assert(64 == sizeof(rand.state)); static_assert(64 == sizeof(rand.state));
AuMemcpy(rand.state, seed.data(), sizeof(rand.state)); AuMemcpy(rand.state, seed.data(), sizeof(rand.state));
return rand; return AuMove(rand);
} }
/** /**

View File

@ -3,12 +3,19 @@
struct WELLRand struct WELLRand
{ {
AuUInt32 state[16]; AuUInt32 state[16];
int index; int index {};
AuThreadPrimitives::SpinLock lock; 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_SeedRand(AuUInt32 seed);
WELLRand WELL_SeedRandBig64(const AuArray<AuUInt8, 64> &seed); WELLRand &&WELL_SeedRandBig64(const AuArray<AuUInt8, 64> &seed);
WELLRand WELL_SeedRand64(AuUInt64 seed); WELLRand &&WELL_SeedRand64(AuUInt64 seed);
AuUInt32 WELL_NextLong(WELLRand* rand); AuUInt32 WELL_NextLong(WELLRand* rand);
void WELL_NextBytes(WELLRand *rand, void *in, AuUInt32 length); void WELL_NextBytes(WELLRand *rand, void *in, AuUInt32 length);