AuroraRuntime/Source/RNG/AuRandomDevice.cpp
Jamie Reece Wilson 77546b5098 [+] IRandomDevice::XXX has VecD variants
[*] Improve: IRandomDevice internal allocations when handling vector arrays
[*] Fix: NextArrayI64RangeInView
2024-09-05 22:50:02 +01:00

1920 lines
58 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuRandomDevice.cpp
Date: 2021-9-3
Author: Reece
***/
#include <AuroraRuntime.hpp>
#include "AuRandomDevice.hpp"
namespace Aurora::RNG
{
static const double kDblEpsilon = 2.2204460492503131e-16;
static thread_local char tlsScratchMemory[2048];
#define RNG_BYTES_PROLOGUE \
AuList<AuUInt64> rngBytes_; \
AuMemoryViewWrite rngBytes;
#define RNG_BYTES_RESIZE(n) \
if (n * sizeof(AuUInt64) < AuArraySize(tlsScratchMemory)) \
{ \
rngBytes = AuMemoryViewWrite(tlsScratchMemory).Take(n * sizeof(AuUInt64)); \
} \
else \
{ \
rngBytes_.resize(n); \
rngBytes = rngBytes_; \
}
#define RNG_BYTES_SIZE \
rngBytes.ToCount<AuUInt64>()
RandomDevice::RandomDevice() :
IO::Adapters::RandomStreamReader(AuUnsafeRaiiToShared(this))
{
}
RandomDevice::RandomDevice(const RandomDef &def) :
IO::Adapters::RandomStreamReader(AuUnsafeRaiiToShared(this))
{
this->Init(def);
}
void RandomDevice::Init(const RandomDef &def)
{
this->def_ = def;
// Gross...
if (!def.bSecure)
{
if (def.seed)
{
this->fast_ = AuMove(WELL_SeedRand(def.seed.value()));
}
else if (def.seed64)
{
this->fast_ = AuMove(WELL_SeedRand64(def.seed64.value()));
}
else if (def.seedMassive)
{
this->fast_ = AuMove(WELL_SeedRandBig64(def.seedMassive.value()));
}
else
{
RNG::RngFillArray<false>(this->fast_.state);
}
}
// secure rng requires no init -> we just passthrough to the global ReadSecureRNG function
}
void RandomDevice::Read(Memory::MemoryViewWrite view)
{
if (!view)
{
SysPushErrorArg();
return;
}
if (this->def_.bSecure)
{
ReadSecureRNG(view);
}
else
{
WELL_NextBytes(&this->fast_, view.ptr, AuUInt32(view.length));
}
}
AuString RandomDevice::NextString(AuUInt32 uLength, ERngStringCharacters type)
{
AuString ret(uLength, '\00');
NextString(ret.data(), AuUInt32(ret.size()), type);
return ret;
}
static double RngConvertToDecimal(AuUInt64 uLargeInt)
{
AuUInt64 qwValue = (uLargeInt & 0xFFFFFFFFFFFFFull) | 0x3FF0000000000000ull;
return *(double *)(&qwValue) - 1.0;
}
void RandomDevice::NextString(char *pString, AuUInt32 uLength, ERngStringCharacters type)
{
static AuPair<const char *, int> rngSequence[static_cast<int>(ERngStringCharacters::eEnumCount)] =
{
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 52},
{"abcdefghijklmnopqrstuvwxyz", 26},
{"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26},
{"1234567890", 10},
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62},
{"abcdefghijklmnopqrstuvwxyz1234567890", 36},
{"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 36},
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!$%^*.[];:", 75}
};
if (!pString)
{
SysPushErrorArg();
return;
}
Read(AuMemoryViewWrite { pString, uLength });
if (!ERngStringCharactersIsValid(type))
{
SysPushErrorArg("NextString was called with an invalid ERngStringCharacters {}", (AuUInt)type);
type = ERngStringCharacters::eAlphaNumericCharacters; // guess we cant just return false
}
const auto &pair = rngSequence[static_cast<int>(type)];
for (auto i = 0u; i < uLength; i++)
{
auto uUpperBound = AuRoundUpPow2(pair.second);
AuUInt8 uNext {};
auto uWord = reinterpret_cast<const AuUInt8 *>(pString)[i];
while ((uNext = (uWord & (uUpperBound - 1))) >= pair.second)
{
uWord = AuFnv1a32Runtime(&uWord, sizeof(uWord));
}
pString[i] = pair.first[uNext];
}
}
AuUInt8 RandomDevice::NextByte()
{
if (this->def_.bSecure)
{
AuUInt8 uRet {};
ReadSecureRNG({ &uRet, 1 });
return uRet;
}
else
{
return AuUInt8(WELL_NextLong(&this->fast_) & 0xFF);
}
}
bool RandomDevice::NextBoolean()
{
if (this->def_.bSecure)
{
AuUInt8 uRet {};
ReadSecureRNG({ &uRet, 1 });
return bool(uRet & 0x1);
}
else
{
return bool(WELL_NextLong(&this->fast_) & 0x1);
}
}
AuUInt32 RandomDevice::NextU32()
{
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::NextI32Range(AuInt32 iMin, AuInt32 iMax)
{
auto uRange = AuUInt32(iMax - iMin);
auto uMassiveWord = NextU32();
auto uUpperBound = AuRoundUpPow2(uRange + 1);
AuUInt32 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a32Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
return iMin + uNext;
}
AuUInt32 RandomDevice::NextU32Range(AuUInt32 uMin, AuUInt32 uMax)
{
auto uRange = uMax - uMin;
auto uMassiveWord = NextU32();
auto uUpperBound = AuRoundUpPow2(uRange + 1);
AuUInt32 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a32Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
return uMin + uNext;
}
// Source: https://stackoverflow.com/a/5016867
bool RandomDevice::DecGeometric(int x)
{
if (x <= 0)
{
return true;
}
while (true)
{
auto r = this->NextByte();
if (x < 8)
{
return (r & ((1 << x) - 1)) == 0;
}
else if (r != 0)
{
return false;
}
x -= 8;
}
}
// Source: https://stackoverflow.com/a/5016867
double RandomDevice::UniformFloatInRange(double udMin, double udMax)
{
// No....
#if defined(AURNG_USE_GARBAGE_DECIMALS)
return (double(this->NextU32()) * (double(1.0) / double(AuNumericLimits<AuUInt32>::max()))) * udMax;
// No....
#elif defined(AURNG_USE_UNIFORM_DECIMALS)
union
{
double f;
AuUInt64 u;
} convert;
convert.f = udMin;
auto uABits = convert.u;
convert.f = udMax;
auto uBBits = convert.u;
auto uMask = uBBits - uABits;
uMask |= uMask >> 1;
uMask |= uMask >> 2;
uMask |= uMask >> 4;
uMask |= uMask >> 8;
uMask |= uMask >> 16;
uMask |= uMask >> 32;
int bExp {};
frexp(udMax, &bExp);
while (true)
{
int iXExp {};
double x;
auto uXBits = this->NextU64();
uXBits &= uMask;
uXBits += uABits;
if (uXBits >= uBBits)
{
continue;
}
convert.u = uXBits;
x = convert.f;
frexp(x, &iXExp);
if (DecGeometric(bExp - iXExp))
{
return x;
}
}
// Yes...
#else
#if !defined(AURNG_USE_FAST_DECIMALS)
#define AURNG_USE_FAST_DECIMALS
return 0.0;
#endif
#endif
}
AuUInt64 RandomDevice::NextU64Range(AuUInt64 uMin, AuUInt64 uMax)
{
auto uRange = uMax - uMin;
auto uMassiveWord = NextU64();
auto uUpperBound = AuRoundUpPow2(uRange + 1);
AuUInt32 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a64Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
return uMin + uNext;
}
AuInt64 RandomDevice::NextI64Range(AuInt64 iMin, AuInt64 iMax)
{
auto uRange = AuUInt64(iMax - iMin);
auto uMassiveWord = NextU64();
auto uUpperBound = AuRoundUpPow2(uRange + 1);
AuUInt32 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a64Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
return iMin + uNext;
}
AuVec2 RandomDevice::NextVec2(AuVec2 boundA, AuVec2 boundB)
{
AuVec2 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
return NextVec2Sorted(mins, maxs);
}
AuVec2 RandomDevice::NextVec2Sorted(AuVec2 min, AuVec2 max)
{
AuVec2 range;
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
auto uSeed = this->NextU64();
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
return AuVec2 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1])
};
}
AuVec3 RandomDevice::NextVec3(AuVec3 boundA, AuVec3 boundB)
{
AuVec3 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
return NextVec3Sorted(mins, maxs);
}
AuVec3 RandomDevice::NextVec3Sorted(AuVec3 min, AuVec3 max)
{
AuVec3 range;
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
auto uSeed = this->NextU64();
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
return AuVec3 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1]),
float((dComponentC * range[2]) + min[2])
};
}
AuVec4 RandomDevice::NextVec4(AuVec4 boundA, AuVec4 boundB)
{
AuVec4 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
mins[3] = AuMin(boundA[3], boundB[3]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
maxs[3] = AuMax(boundA[3], boundB[3]);
return NextVec4Sorted(mins, maxs);
}
AuVec4 RandomDevice::NextVec4Sorted(AuVec4 min, AuVec4 max)
{
AuVec4 range;
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
range[3] = max[3] - min[3];
auto uSeed = this->NextU64();
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentD = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
return AuVec4 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1]),
float((dComponentC * range[2]) + min[2]),
float((dComponentD * range[3]) + min[3])
};
}
AuVecD2 RandomDevice::NextVecD2(AuVecD2 boundA, AuVecD2 boundB)
{
AuVecD2 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
return NextVecD2Sorted(mins, maxs);
}
AuVecD2 RandomDevice::NextVecD2Sorted(AuVecD2 min, AuVecD2 max)
{
AuVecD2 range;
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
auto uSeed = this->NextU64();
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
return AuVecD2 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1]
};
}
AuVecD3 RandomDevice::NextVecD3(AuVecD3 boundA, AuVecD3 boundB)
{
AuVecD3 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
return NextVecD3Sorted(mins, maxs);
}
AuVecD3 RandomDevice::NextVecD3Sorted(AuVecD3 min, AuVecD3 max)
{
AuVecD3 range;
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
auto uSeed = this->NextU64();
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
return AuVecD3 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1],
(dComponentC * range[2]) + min[2]
};
}
AuVecD4 RandomDevice::NextVecD4(AuVecD4 boundA, AuVecD4 boundB)
{
AuVecD4 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
mins[3] = AuMin(boundA[3], boundB[3]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
maxs[3] = AuMax(boundA[3], boundB[3]);
return NextVecD4Sorted(mins, maxs);
}
AuVecD4 RandomDevice::NextVecD4Sorted(AuVecD4 min, AuVecD4 max)
{
AuVecD4 range;
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
range[3] = max[3] - min[3];
auto uSeed = this->NextU64();
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentD = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
return AuVecD4 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1],
(dComponentC * range[2]) + min[2],
(dComponentD * range[3]) + min[3]
};
}
double RandomDevice::NextDecimal()
{
// fast decimals are the default
#if defined(AURNG_USE_FAST_DECIMALS)
return RngConvertToDecimal(this->NextU64());
#elif defined(AURNG_USE_UNIFORM_DECIMALS)
return this->UniformFloatInRange(kDblEpsilon, 1.0 + kDblEpsilon) - kDblEpsilon;
#elif defined(AURNG_USE_GARBAGE_DECIMALS)
return this->UniformFloatInRange(0, 1.0);
#else
return 0;
#endif
}
AuUInt32 RandomDevice::NextIndex(AuUInt32 uCount /* = max + 1*/)
{
auto uMassiveWord = NextU32();
auto uUpperBound = AuRoundUpPow2(uCount);
AuUInt32 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) >= uCount)
{
uMassiveWord = AuFnv1a32Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
return uNext;
}
double RandomDevice::NextNumber(double dMin, double dMax)
{
auto dRange = dMax - dMin;
#if defined(AURNG_USE_FAST_DECIMALS)
return (this->NextDecimal() * dRange) + dMin;
#else
// potentially not deterministic, thanks to runtime/platform deviations
return this->UniformFloatInRange(kDblEpsilon, dRange + kDblEpsilon) + dMin - kDblEpsilon;
#endif
}
uuids::uuid RandomDevice::NextUUID()
{
AuUInt8 bytes[16];
this->Read(bytes);
bytes[8] &= 0xBF;
bytes[8] |= 0x80;
bytes[6] &= 0x4F;
bytes[6] |= 0x40;
return uuids::uuid { bytes, bytes + 16 };
}
AuUInt RandomDevice::NextArrayI32RangeInView(AuMemoryViewWrite write, AuInt32 iMin, AuInt32 iMax)
{
auto ret = write.Begin<AuInt32>();
auto uCount = write.ToCount<AuInt32>();
this->Read(write);
auto uRange = AuUInt32(iMax - iMin);
auto uUpperBound = AuRoundUpPow2(uRange + 1);
for (AU_ITERATE_N(uIndex, uCount))
{
auto uMassiveWord = write.Begin<AuUInt32>()[uIndex];
AuUInt32 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a32Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
ret[uIndex] = iMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayI32RangeFastInView(AuMemoryViewWrite write, AuInt32 iMin, AuInt32 iMax)
{
auto ret = write.Begin<AuInt32>();
auto uCount = write.ToCount<AuInt32>();
auto uRange = AuUInt32(iMax - iMin);
auto uUpperBound = AuRoundUpPow2(uRange + 1);
auto uSeed = this->NextU32();
for (AU_ITERATE_N(uIndex, uCount))
{
AuUInt32 uNext {};
uSeed = AuFnv1a32Runtime<sizeof(uSeed)>(&uSeed);
while ((uNext = (uSeed & (uUpperBound - 1))) > uRange)
{
uSeed = AuFnv1a32Runtime<sizeof(uSeed)>(&uSeed);
}
ret[uIndex] = iMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayU32RangeInView(AuMemoryViewWrite write, AuUInt32 uMin, AuUInt32 uMax)
{
auto ret = write.Begin<AuUInt32>();
auto uCount = write.ToCount<AuUInt32>();
this->Read(write);
auto uRange = uMax - uMin;
auto uUpperBound = AuRoundUpPow2(uRange + 1);
for (AU_ITERATE_N(uIndex, uCount))
{
auto uMassiveWord = ret[uIndex];
AuUInt32 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a32Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
ret[uIndex] = uMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayU32RangeFastInView(AuMemoryViewWrite write, AuUInt32 uMin, AuUInt32 uMax)
{
auto ret = write.Begin<AuUInt32>();
auto uCount = write.ToCount<AuUInt32>();
auto uRange = uMax - uMin;
auto uUpperBound = AuRoundUpPow2(uRange + 1);
auto uSeed = this->NextU32();
for (AU_ITERATE_N(uIndex, uCount))
{
AuUInt32 uNext {};
uSeed = AuFnv1a32Runtime<sizeof(uSeed)>(&uSeed);
while ((uNext = (uSeed & (uUpperBound - 1))) > uRange)
{
uSeed = AuFnv1a32Runtime<sizeof(uSeed)>(&uSeed);
}
ret[uIndex] = uMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayDoubleRangeInView(AuMemoryViewWrite write, double dMin, double dMax)
{
#if defined(AURNG_USE_FAST_DECIMALS)
auto ret = write.Begin<double>();
auto uCount = write.ToCount<double>();
double dRange = dMax - dMin;
if constexpr (sizeof(double) == sizeof(AuUInt64))
{
this->Read(write);
for (AU_ITERATE_N(uIndex, uCount))
{
double dValue = RngConvertToDecimal(*(AuUInt64 *)&ret[uIndex]);
dValue *= dRange;
dValue += dMin;
ret[uIndex] = dValue;
}
}
else
{
RNG_BYTES_PROLOGUE;
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
double dValue = RngConvertToDecimal(rngBytes.Begin<AuUInt64>()[uIndex]);
dValue *= dRange;
dValue += dMin;
ret[uIndex] = dValue;
}
}
return uCount;
#else
auto ret = write.Begin<double>();
auto uCount = write.ToCount<double>();
for (AU_ITERATE_N(uIndex, uCount))
{
ret[uIndex] = this->NextNumber(dMin, dMax);
}
return uCount;
#endif
}
AuUInt RandomDevice::NextArrayDoubleRangeFastInView(AuMemoryViewWrite write, double dMin, double dMax)
{
auto ret = write.Begin<double>();
auto uCount = write.ToCount<double>();
AuUInt64 uSeed = this->NextU64();
double dRange = dMax - dMin;
for (AU_ITERATE_N(uIndex, uCount))
{
double dValue = RngConvertToDecimal(uSeed);
dValue *= dRange;
dValue += dMin;
ret[uIndex] = dValue;
uSeed = AuFnv1a64Runtime<8>(&uSeed);
}
return uCount;
}
AuUInt RandomDevice::NextArrayI32InView(AuMemoryViewWrite write)
{
auto ret = write.Begin<AuInt32>();
auto uCount = write.ToCount<AuInt32>();
this->Read(write);
return uCount;
}
AuUInt RandomDevice::NextArrayU32InView(AuMemoryViewWrite write)
{
auto ret = write.Begin<AuUInt32>();
auto uCount = write.ToCount<AuUInt32>();
this->Read(write);
return uCount;
}
AuUInt RandomDevice::NextArrayI64RangeFastInView(AuMemoryViewWrite write, AuInt64 iMin, AuInt64 iMax)
{
auto ret = write.Begin<AuInt64>();
auto uCount = write.ToCount<AuInt64>();
auto uRange = AuUInt64(iMax - iMin);
auto uUpperBound = AuRoundUpPow2(uRange + 1);
auto uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
AuUInt64 uNext {};
uSeed = AuFnv1a64Runtime<sizeof(uSeed)>(&uSeed);
while ((uNext = (uSeed & (uUpperBound - 1))) > uRange)
{
uSeed = AuFnv1a64Runtime<sizeof(uSeed)>(&uSeed);
}
ret[uIndex] = iMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayU64RangeFastInView(AuMemoryViewWrite write, AuUInt64 uMin, AuUInt64 uMax)
{
auto ret = write.Begin<AuUInt64>();
auto uCount = write.ToCount<AuUInt64>();
auto uRange = uMax - uMin;
auto uUpperBound = AuRoundUpPow2(uRange + 1);
auto uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
AuUInt64 uNext {};
uSeed = AuFnv1a64Runtime<sizeof(uSeed)>(&uSeed);
while ((uNext = (uSeed & (uUpperBound - 1))) > uRange)
{
uSeed = AuFnv1a64Runtime<sizeof(uSeed)>(&uSeed);
}
ret[uIndex] = uMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayI64RangeInView(AuMemoryViewWrite write, AuInt64 iMin, AuInt64 iMax)
{
auto ret = write.Begin<AuInt64>();
auto uCount = write.ToCount<AuInt64>();
this->Read(write);
auto uRange = AuUInt64(iMax - iMin);
auto uUpperBound = AuRoundUpPow2(uRange + 1);
for (AU_ITERATE_N(uIndex, uCount))
{
auto uMassiveWord = write.Begin<AuUInt64>()[uIndex];
AuUInt64 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a64Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
ret[uIndex] = iMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayU64RangeInView(AuMemoryViewWrite write, AuUInt64 uMin, AuUInt64 uMax)
{
auto ret = write.Begin<AuUInt64>();
auto uCount = write.ToCount<AuUInt64>();
this->Read(write);
auto uRange = uMax - uMin;
auto uUpperBound = AuRoundUpPow2(uRange + 1);
for (AU_ITERATE_N(uIndex, uCount))
{
auto uMassiveWord = ret[uIndex];
AuUInt64 uNext {};
while ((uNext = (uMassiveWord & (uUpperBound - 1))) > uRange)
{
uMassiveWord = AuFnv1a64Runtime<sizeof(uMassiveWord)>(&uMassiveWord);
}
ret[uIndex] = uMin + uNext;
}
return uCount;
}
AuUInt RandomDevice::NextArrayU32MaskInView(AuMemoryViewWrite write, AuUInt32 uMask)
{
auto ret = write.Begin<AuUInt32>();
auto uCount = write.ToCount<AuUInt32>();
this->Read(write);
for (AU_ITERATE_N(i, uCount))
{
auto &word = ret[i];
word &= uMask;
}
return uCount;
}
AuUInt RandomDevice::NextArrayU64MaskInView(AuMemoryViewWrite write, AuUInt64 uMask)
{
auto ret = write.Begin<AuUInt64>();
auto uCount = write.ToCount<AuUInt64>();
this->Read(write);
for (AU_ITERATE_N(i, uCount))
{
auto &word = ret[i];
word &= uMask;
}
return uCount;
}
AuUInt RandomDevice::NextArrayI64InView(AuMemoryViewWrite write)
{
auto uCount = write.ToCount<AuInt64>();
this->Read(write);
return uCount;
}
AuUInt RandomDevice::NextArrayU64InView(AuMemoryViewWrite write)
{
auto uCount = write.ToCount<AuUInt64>();
this->Read(write);
return uCount;
}
AuUInt RandomDevice::NextArrayVec2InView(AuMemoryViewWrite write, AuVec2 boundA, AuVec2 boundB)
{
AuVec2 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
return NextArrayVec2SortedInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVec2FastInView(AuMemoryViewWrite write, AuVec2 boundA, AuVec2 boundB)
{
AuVec2 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
return NextArrayVec2SortedFastInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVec2SortedInView(AuMemoryViewWrite write, AuVec2 min, AuVec2 max)
{
AuVec2 range;
RNG_BYTES_PROLOGUE;
auto ret = write.Begin<AuVec2>();
auto uCount = write.ToCount<AuVec2>();
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
auto uSeed = rngBytes.Begin<AuUInt64>()[uIndex];
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVec2 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1])
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVec2SortedFastInView(AuMemoryViewWrite write, AuVec2 min, AuVec2 max)
{
AuVec2 range;
auto ret = write.Begin<AuVec2>();
auto uCount = write.ToCount<AuVec2>();
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
AuUInt64 uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
auto dComponentA = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVec2 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1])
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVec3InView(AuMemoryViewWrite write, AuVec3 boundA, AuVec3 boundB)
{
AuVec3 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
return NextArrayVec3SortedInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVec3FastInView(AuMemoryViewWrite write, AuVec3 boundA, AuVec3 boundB)
{
AuVec3 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
return NextArrayVec3SortedFastInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVec3SortedInView(AuMemoryViewWrite write, AuVec3 min, AuVec3 max)
{
AuVec3 range;
RNG_BYTES_PROLOGUE;
auto ret = write.Begin<AuVec3>();
auto uCount = write.ToCount<AuVec3>();
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
auto uSeed = rngBytes.Begin<AuUInt64>()[uIndex];
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVec3 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1]),
float((dComponentC * range[2]) + min[2])
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVec3SortedFastInView(AuMemoryViewWrite write, AuVec3 min, AuVec3 max)
{
AuVec3 range;
auto ret = write.Begin<AuVec3>();
auto uCount = write.ToCount<AuVec3>();
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
AuUInt64 uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
auto dComponentA = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVec3 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1]),
float((dComponentC * range[2]) + min[2])
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVec4InView(AuMemoryViewWrite write, AuVec4 boundA, AuVec4 boundB)
{
AuVec4 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
mins[3] = AuMin(boundA[3], boundB[3]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
maxs[3] = AuMax(boundA[3], boundB[3]);
return NextArrayVec4SortedInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVec4FastInView(AuMemoryViewWrite write, AuVec4 boundA, AuVec4 boundB)
{
AuVec4 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
mins[3] = AuMin(boundA[3], boundB[3]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
maxs[3] = AuMax(boundA[3], boundB[3]);
return NextArrayVec4SortedFastInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVec4SortedInView(AuMemoryViewWrite write, AuVec4 min, AuVec4 max)
{
AuVec4 range;
RNG_BYTES_PROLOGUE;
auto ret = write.Begin<AuVec4>();
auto uCount = write.ToCount<AuVec4>();
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
range[3] = max[3] - min[3];
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
auto uSeed = rngBytes.Begin<AuUInt64>()[uIndex];
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentD = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVec4 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1]),
float((dComponentC * range[2]) + min[2]),
float((dComponentD * range[3]) + min[3])
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVec4SortedFastInView(AuMemoryViewWrite write, AuVec4 min, AuVec4 max)
{
AuVec4 range;
auto ret = write.Begin<AuVec4>();
auto uCount = write.ToCount<AuVec4>();
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
range[3] = max[3] - min[3];
AuUInt64 uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
auto dComponentA = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentD = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVec4 {
float((dComponentA * range[0]) + min[0]),
float((dComponentB * range[1]) + min[1]),
float((dComponentC * range[2]) + min[2]),
float((dComponentD * range[3]) + min[3])
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVecD2InView(AuMemoryViewWrite write, AuVecD2 boundA, AuVecD2 boundB)
{
AuVecD2 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
return NextArrayVecD2SortedInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVecD2FastInView(AuMemoryViewWrite write, AuVecD2 boundA, AuVecD2 boundB)
{
AuVecD2 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
return NextArrayVecD2SortedFastInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVecD2SortedInView(AuMemoryViewWrite write, AuVecD2 min, AuVecD2 max)
{
AuVecD2 range;
RNG_BYTES_PROLOGUE;
auto ret = write.Begin<AuVecD2>();
auto uCount = write.ToCount<AuVecD2>();
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
auto uSeed = rngBytes.Begin<AuUInt64>()[uIndex];
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVecD2 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1]
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVecD2SortedFastInView(AuMemoryViewWrite write, AuVecD2 min, AuVecD2 max)
{
AuVecD2 range;
auto ret = write.Begin<AuVecD2>();
auto uCount = write.ToCount<AuVecD2>();
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
AuUInt64 uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
auto dComponentA = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVecD2 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1]
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVecD3InView(AuMemoryViewWrite write, AuVecD3 boundA, AuVecD3 boundB)
{
AuVecD3 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
return NextArrayVecD3SortedInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVecD3FastInView(AuMemoryViewWrite write, AuVecD3 boundA, AuVecD3 boundB)
{
AuVecD3 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
return NextArrayVecD3SortedFastInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVecD3SortedInView(AuMemoryViewWrite write, AuVecD3 min, AuVecD3 max)
{
AuVecD3 range;
RNG_BYTES_PROLOGUE;
auto ret = write.Begin<AuVecD3>();
auto uCount = write.ToCount<AuVecD3>();
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
auto uSeed = rngBytes.Begin<AuUInt64>()[uIndex];
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVecD3 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1],
(dComponentC * range[2]) + min[2]
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVecD3SortedFastInView(AuMemoryViewWrite write, AuVecD3 min, AuVecD3 max)
{
AuVecD3 range;
auto ret = write.Begin<AuVecD3>();
auto uCount = write.ToCount<AuVecD3>();
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
AuUInt64 uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
auto dComponentA = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVecD3 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1],
(dComponentC * range[2]) + min[2]
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVecD4InView(AuMemoryViewWrite write, AuVecD4 boundA, AuVecD4 boundB)
{
AuVecD4 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
mins[3] = AuMin(boundA[3], boundB[3]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
maxs[3] = AuMax(boundA[3], boundB[3]);
return NextArrayVecD4SortedInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVecD4FastInView(AuMemoryViewWrite write, AuVecD4 boundA, AuVecD4 boundB)
{
AuVecD4 mins, maxs;
mins[0] = AuMin(boundA[0], boundB[0]);
mins[1] = AuMin(boundA[1], boundB[1]);
mins[2] = AuMin(boundA[2], boundB[2]);
mins[3] = AuMin(boundA[3], boundB[3]);
maxs[0] = AuMax(boundA[0], boundB[0]);
maxs[1] = AuMax(boundA[1], boundB[1]);
maxs[2] = AuMax(boundA[2], boundB[2]);
maxs[3] = AuMax(boundA[3], boundB[3]);
return NextArrayVecD4SortedFastInView(write, mins, maxs);
}
AuUInt RandomDevice::NextArrayVecD4SortedInView(AuMemoryViewWrite write, AuVecD4 min, AuVecD4 max)
{
AuVecD4 range;
RNG_BYTES_PROLOGUE;
auto ret = write.Begin<AuVecD4>();
auto uCount = write.ToCount<AuVecD4>();
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
range[3] = max[3] - min[3];
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
auto uSeed = rngBytes.Begin<AuUInt64>()[uIndex];
auto dComponentA = RngConvertToDecimal(uSeed);
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentD = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVecD4 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1],
(dComponentC * range[2]) + min[2],
(dComponentD * range[3]) + min[3]
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayVecD4SortedFastInView(AuMemoryViewWrite write, AuVecD4 min, AuVecD4 max)
{
AuVecD4 range;
auto ret = write.Begin<AuVecD4>();
auto uCount = write.ToCount<AuVecD4>();
range[0] = max[0] - min[0];
range[1] = max[1] - min[1];
range[2] = max[2] - min[2];
range[3] = max[3] - min[3];
AuUInt64 uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
auto dComponentA = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentB = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentC = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
auto dComponentD = RngConvertToDecimal(uSeed = (AuFnv1a64Runtime<8>(&uSeed)));
ret[uIndex] = AuVecD4 {
(dComponentA * range[0]) + min[0],
(dComponentB * range[1]) + min[1],
(dComponentC * range[2]) + min[2],
(dComponentD * range[3]) + min[3]
};
}
return uCount;
}
AuUInt RandomDevice::NextArrayDoubleInView(AuMemoryViewWrite write)
{
auto ret = write.Begin<double>();
auto uCount = write.ToCount<double>();
this->Read(write);
return uCount;
}
AuUInt RandomDevice::NextArrayDecimalsInView(AuMemoryViewWrite write)
{
#if defined(AURNG_USE_FAST_DECIMALS)
auto ret = write.Begin<double>();
auto uCount = write.ToCount<double>();
if constexpr (sizeof(double) == sizeof(AuUInt64))
{
this->Read(write);
for (AU_ITERATE_N(uIndex, uCount))
{
ret[uIndex] = RngConvertToDecimal(*(AuUInt64*)&ret[uIndex]);
}
}
else
{
RNG_BYTES_PROLOGUE;
RNG_BYTES_RESIZE(uCount);
this->Read(rngBytes);
for (AU_ITERATE_N(uIndex, RNG_BYTES_SIZE))
{
ret[uIndex] = RngConvertToDecimal(rngBytes.Begin<AuUInt64>()[uIndex]);
}
}
return uCount;
#else
auto ret = write.Begin<double>();
auto uCount = write.ToCount<double>();
for (AU_ITERATE_N(uIndex, uCount))
{
ret[uIndex] = this->NextDecimal();
}
return uCount;
#endif
}
AuUInt RandomDevice::NextArrayDecimalsFastInView(AuMemoryViewWrite write)
{
auto ret = write.Begin<double>();
auto uCount = write.ToCount<double>();
AuUInt64 uSeed = this->NextU64();
for (AU_ITERATE_N(uIndex, uCount))
{
ret[uIndex] = RngConvertToDecimal(uSeed);
uSeed = AuFnv1a64Runtime<8>(&uSeed);
}
return uCount;
}
AuUInt RandomDevice::NextArrayUUIDsInView(AuMemoryViewWrite write)
{
auto ret = write.Begin<uuids::uuid>();
auto uCount = write.ToCount<uuids::uuid>();
if constexpr (sizeof(uuids::uuid) == 16)
{
this->Read(write);
for (AU_ITERATE_N(uIndex, uCount))
{
auto pBytes = write.Begin<AuUInt8>() + (uIndex * 16);
pBytes[8] &= 0xBF;
pBytes[8] |= 0x80;
pBytes[6] &= 0x4F;
pBytes[6] |= 0x40;
}
}
else
{
AuList<AuUInt8> rngBytes;
rngBytes.resize(uCount * 16);
this->Read(rngBytes);
for (AU_ITERATE_N(uIndex, uCount))
{
auto pBytes = rngBytes.data() + (uIndex * 16);
pBytes[8] &= 0xBF;
pBytes[8] |= 0x80;
pBytes[6] &= 0x4F;
pBytes[6] |= 0x40;
ret[uIndex] = uuids::uuid { pBytes, pBytes + 16 };
}
}
return uCount;
}
AuList<AuInt32> RandomDevice::NextArrayI32Range(AuUInt32 uCount, AuInt32 iMin, AuInt32 iMax)
{
AuList<AuInt32> ret;
ret.resize(uCount);
(void)NextArrayI32RangeInView(ret, iMin, iMax);
return ret;
}
AuList<AuInt32> RandomDevice::NextArrayI32RangeFast(AuUInt32 uCount, AuInt32 iMin, AuInt32 iMax)
{
AuList<AuInt32> ret;
ret.resize(uCount);
(void)NextArrayI32RangeFastInView(ret, iMin, iMax);
return ret;
}
AuList<AuUInt32> RandomDevice::NextArrayU32Range(AuUInt32 uCount, AuUInt32 uMin, AuUInt32 uMax)
{
AuList<AuUInt32> ret;
ret.resize(uCount);
(void)NextArrayU32RangeInView(ret, uMin, uMax);
return ret;
}
AuList<AuUInt32> RandomDevice::NextArrayU32RangeFast(AuUInt32 uCount, AuUInt32 uMin, AuUInt32 uMax)
{
AuList<AuUInt32> ret;
ret.resize(uCount);
(void)NextArrayU32RangeFastInView(ret, uMin, uMax);
return ret;
}
AuList<double> RandomDevice::NextArrayDoubleRange(AuUInt32 uCount, double dMin, double dMax)
{
AuList<double> ret;
ret.resize(uCount);
(void)NextArrayDoubleRangeInView(ret, dMin, dMax);
return ret;
}
AuList<double> RandomDevice::NextArrayDoubleRangeFast(AuUInt32 uCount, double dMin, double dMax)
{
AuList<double> ret;
ret.resize(uCount);
(void)NextArrayDoubleRangeFastInView(ret, dMin, dMax);
return ret;
}
AuList<AuInt32> RandomDevice::NextArrayI32(AuUInt32 uCount)
{
AuList<AuInt32> ret;
ret.resize(uCount);
(void)NextArrayI32InView(ret);
return ret;
}
AuList<AuUInt32> RandomDevice::NextArrayU32(AuUInt32 uCount)
{
AuList<AuUInt32> ret;
ret.resize(uCount);
(void)NextArrayU32InView(ret);
return ret;
}
AuList<AuInt64> RandomDevice::NextArrayI64RangeFast(AuUInt32 uCount, AuInt64 iMin, AuInt64 iMax)
{
AuList<AuInt64> ret;
ret.resize(uCount);
(void)NextArrayI64RangeFastInView(ret, iMin, iMax);
return ret;
}
AuList<AuUInt64> RandomDevice::NextArrayU64RangeFast(AuUInt32 uCount, AuUInt64 uMin, AuUInt64 uMax)
{
AuList<AuUInt64> ret;
ret.resize(uCount);
(void)NextArrayU64RangeFastInView(ret, uMin, uMax);
return ret;
}
AuList<AuInt64> RandomDevice::NextArrayI64Range(AuUInt32 uCount, AuInt64 iMin, AuInt64 iMax)
{
AuList<AuInt64> ret;
ret.resize(uCount);
(void)NextArrayI64RangeInView(ret, iMin, iMax);
return ret;
}
AuList<AuUInt64> RandomDevice::NextArrayU64Range(AuUInt32 uCount, AuUInt64 uMin, AuUInt64 uMax)
{
AuList<AuUInt64> ret;
ret.resize(uCount);
(void)NextArrayU64RangeInView(ret, uMin, uMax);
return ret;
}
AuList<AuUInt32> RandomDevice::NextArrayU32Mask(AuUInt32 uCount, AuUInt32 uMask)
{
AuList<AuUInt32> ret;
ret.resize(uCount);
(void)NextArrayU32MaskInView(ret, uMask);
return ret;
}
AuList<AuUInt64> RandomDevice::NextArrayU64Mask(AuUInt32 uCount, AuUInt64 uMask)
{
AuList<AuUInt64> ret;
ret.resize(uCount);
(void)NextArrayU64MaskInView(ret, uMask);
return ret;
}
AuList<AuInt64> RandomDevice::NextArrayI64(AuUInt32 uCount)
{
AuList<AuInt64> ret;
ret.resize(uCount);
(void)NextArrayI64InView(ret);
return ret;
}
AuList<AuUInt64> RandomDevice::NextArrayU64(AuUInt32 uCount)
{
AuList<AuUInt64> ret;
ret.resize(uCount);
(void)NextArrayU64InView(ret);
return ret;
}
AuList<AuVec2> RandomDevice::NextArrayVec2(AuUInt32 uCount, AuVec2 boundA, AuVec2 boundB)
{
AuList<AuVec2> ret;
ret.resize(uCount);
(void)NextArrayVec2InView(ret, boundA, boundB);
return ret;
}
AuList<AuVec2> RandomDevice::NextArrayVec2Fast(AuUInt32 uCount, AuVec2 boundA, AuVec2 boundB)
{
AuList<AuVec2> ret;
ret.resize(uCount);
(void)NextArrayVec2FastInView(ret, boundA, boundB);
return ret;
}
AuList<AuVec2> RandomDevice::NextArrayVec2Sorted(AuUInt32 uCount, AuVec2 min, AuVec2 max)
{
AuList<AuVec2> ret;
ret.resize(uCount);
(void)NextArrayVec2SortedInView(ret, min, max);
return ret;
}
AuList<AuVec2> RandomDevice::NextArrayVec2SortedFast(AuUInt32 uCount, AuVec2 min, AuVec2 max)
{
AuList<AuVec2> ret;
ret.resize(uCount);
(void)NextArrayVec2SortedFastInView(ret, min, max);
return ret;
}
AuList<AuVec3> RandomDevice::NextArrayVec3(AuUInt32 uCount, AuVec3 boundA, AuVec3 boundB)
{
AuList<AuVec3> ret;
ret.resize(uCount);
(void)NextArrayVec3InView(ret, boundA, boundB);
return ret;
}
AuList<AuVec3> RandomDevice::NextArrayVec3Fast(AuUInt32 uCount, AuVec3 boundA, AuVec3 boundB)
{
AuList<AuVec3> ret;
ret.resize(uCount);
(void)NextArrayVec3FastInView(ret, boundA, boundB);
return ret;
}
AuList<AuVec3> RandomDevice::NextArrayVec3Sorted(AuUInt32 uCount, AuVec3 min, AuVec3 max)
{
AuList<AuVec3> ret;
ret.resize(uCount);
(void)NextArrayVec3SortedInView(ret, min, max);
return ret;
}
AuList<AuVec3> RandomDevice::NextArrayVec3SortedFast(AuUInt32 uCount, AuVec3 min, AuVec3 max)
{
AuList<AuVec3> ret;
ret.resize(uCount);
(void)NextArrayVec3SortedFastInView(ret, min, max);
return ret;
}
AuList<AuVec4> RandomDevice::NextArrayVec4(AuUInt32 uCount, AuVec4 boundA, AuVec4 boundB)
{
AuList<AuVec4> ret;
ret.resize(uCount);
(void)NextArrayVec4InView(ret, boundA, boundB);
return ret;
}
AuList<AuVec4> RandomDevice::NextArrayVec4Fast(AuUInt32 uCount, AuVec4 boundA, AuVec4 boundB)
{
AuList<AuVec4> ret;
ret.resize(uCount);
(void)NextArrayVec4FastInView(ret, boundA, boundB);
return ret;
}
AuList<AuVec4> RandomDevice::NextArrayVec4Sorted(AuUInt32 uCount, AuVec4 min, AuVec4 max)
{
AuList<AuVec4> ret;
ret.resize(uCount);
(void)NextArrayVec4SortedInView(ret, min, max);
return ret;
}
AuList<AuVec4> RandomDevice::NextArrayVec4SortedFast(AuUInt32 uCount, AuVec4 min, AuVec4 max)
{
AuList<AuVec4> ret;
ret.resize(uCount);
(void)NextArrayVec4SortedFastInView(ret, min, max);
return ret;
}
AuList<AuVecD2> RandomDevice::NextArrayVecD2(AuUInt32 uCount, AuVecD2 boundA, AuVecD2 boundB)
{
AuList<AuVecD2> ret;
ret.resize(uCount);
(void)NextArrayVecD2InView(ret, boundA, boundB);
return ret;
}
AuList<AuVecD2> RandomDevice::NextArrayVecD2Fast(AuUInt32 uCount, AuVecD2 boundA, AuVecD2 boundB)
{
AuList<AuVecD2> ret;
ret.resize(uCount);
(void)NextArrayVecD2FastInView(ret, boundA, boundB);
return ret;
}
AuList<AuVecD2> RandomDevice::NextArrayVecD2Sorted(AuUInt32 uCount, AuVecD2 min, AuVecD2 max)
{
AuList<AuVecD2> ret;
ret.resize(uCount);
(void)NextArrayVecD2SortedInView(ret, min, max);
return ret;
}
AuList<AuVecD2> RandomDevice::NextArrayVecD2SortedFast(AuUInt32 uCount, AuVecD2 min, AuVecD2 max)
{
AuList<AuVecD2> ret;
ret.resize(uCount);
(void)NextArrayVecD2SortedFastInView(ret, min, max);
return ret;
}
AuList<AuVecD3> RandomDevice::NextArrayVecD3(AuUInt32 uCount, AuVecD3 boundA, AuVecD3 boundB)
{
AuList<AuVecD3> ret;
ret.resize(uCount);
(void)NextArrayVecD3InView(ret, boundA, boundB);
return ret;
}
AuList<AuVecD3> RandomDevice::NextArrayVecD3Fast(AuUInt32 uCount, AuVecD3 boundA, AuVecD3 boundB)
{
AuList<AuVecD3> ret;
ret.resize(uCount);
(void)NextArrayVecD3FastInView(ret, boundA, boundB);
return ret;
}
AuList<AuVecD3> RandomDevice::NextArrayVecD3Sorted(AuUInt32 uCount, AuVecD3 min, AuVecD3 max)
{
AuList<AuVecD3> ret;
ret.resize(uCount);
(void)NextArrayVecD3SortedInView(ret, min, max);
return ret;
}
AuList<AuVecD3> RandomDevice::NextArrayVecD3SortedFast(AuUInt32 uCount, AuVecD3 min, AuVecD3 max)
{
AuList<AuVecD3> ret;
ret.resize(uCount);
(void)NextArrayVecD3SortedFastInView(ret, min, max);
return ret;
}
AuList<AuVecD4> RandomDevice::NextArrayVecD4(AuUInt32 uCount, AuVecD4 boundA, AuVecD4 boundB)
{
AuList<AuVecD4> ret;
ret.resize(uCount);
(void)NextArrayVecD4InView(ret, boundA, boundB);
return ret;
}
AuList<AuVecD4> RandomDevice::NextArrayVecD4Fast(AuUInt32 uCount, AuVecD4 boundA, AuVecD4 boundB)
{
AuList<AuVecD4> ret;
ret.resize(uCount);
(void)NextArrayVecD4FastInView(ret, boundA, boundB);
return ret;
}
AuList<AuVecD4> RandomDevice::NextArrayVecD4Sorted(AuUInt32 uCount, AuVecD4 min, AuVecD4 max)
{
AuList<AuVecD4> ret;
ret.resize(uCount);
(void)NextArrayVecD4SortedInView(ret, min, max);
return ret;
}
AuList<AuVecD4> RandomDevice::NextArrayVecD4SortedFast(AuUInt32 uCount, AuVecD4 min, AuVecD4 max)
{
AuList<AuVecD4> ret;
ret.resize(uCount);
(void)NextArrayVecD4SortedFastInView(ret, min, max);
return ret;
}
AuList<double> RandomDevice::NextArrayDouble(AuUInt32 uCount)
{
AuList<double> ret;
ret.resize(uCount);
(void)NextArrayDoubleInView(ret);
return ret;
}
AuList<double> RandomDevice::NextArrayDecimals(AuUInt32 uCount)
{
AuList<double> ret;
ret.resize(uCount);
(void)NextArrayDecimalsInView(ret);
return ret;
}
AuList<double> RandomDevice::NextArrayDecimalsFast(AuUInt32 uCount)
{
AuList<double> ret;
ret.resize(uCount);
(void)NextArrayDecimalsFastInView(ret);
return ret;
}
AuList<uuids::uuid> RandomDevice::NextArrayUUIDs(AuUInt32 uCount)
{
AuList<uuids::uuid> ret;
ret.resize(uCount);
(void)NextArrayUUIDsInView(ret);
return ret;
}
AuMemoryViewRead RandomDevice::ToSeed()
{
if (this->def_.bSecure)
{
return {};
}
return this->fast_.state;
}
IO::IStreamReader *RandomDevice::ToStreamReader()
{
return this;
}
AUKN_SYM IRandomDevice *RandomNew(const Aurora::RNG::RandomDef &def)
{
auto pDevice = _new RandomDevice();
if (!pDevice)
{
return nullptr;
}
pDevice->Init(def);
return pDevice;
}
AUKN_SYM void RandomRelease(IRandomDevice *pDevice)
{
AuSafeDelete<RandomDevice *>(pDevice);
}
AUROXTL_INTERFACE_SOO_SRC(Random, RandomDevice, (const RandomDef &, def))
}