[*] 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:
parent
e3cecc2d35
commit
999f3e69ca
@ -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()
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
Loading…
Reference in New Issue
Block a user