/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: IRandomDevice.hpp Date: 2021-9-3 Author: Reece ***/ #pragma once namespace Aurora::RNG { static const auto kSizeRNGDevice = 256; struct IRandomDevice { virtual IO::IStreamReader * ToStreamReader() = 0; virtual Memory::MemoryViewRead ToSeed() = 0; virtual void Read(Memory::MemoryViewWrite view) = 0; virtual AuString NextString(AuUInt32 uLength, ERngStringCharacters type = ERngStringCharacters::eAlphaCharacters) = 0; virtual void NextString(char *pString, AuUInt32 uLength, ERngStringCharacters type = ERngStringCharacters::eAlphaCharacters) = 0; virtual AuUInt8 NextByte() = 0; virtual bool NextBoolean() = 0; virtual AuUInt32 NextU32() = 0; virtual AuUInt32 NextU32Range(AuUInt32 uMin, AuUInt32 uMax) = 0; virtual AuInt32 NextI32Range(AuInt32 iMin, AuInt32 iMax) = 0; virtual AuUInt64 NextU64() = 0; virtual AuUInt64 NextU64Range(AuUInt64 uMin, AuUInt64 uMax) = 0; virtual AuInt64 NextI64Range(AuInt64 iMin, AuInt64 iMax) = 0; virtual AuVec2 NextVec2(AuVec2 boundA, AuVec2 boundB) = 0; virtual AuVec2 NextVec2Sorted(AuVec2 min, AuVec2 max) = 0; virtual AuVec3 NextVec3(AuVec3 boundA, AuVec3 boundB) = 0; virtual AuVec3 NextVec3Sorted(AuVec3 min, AuVec3 max) = 0; virtual AuVec4 NextVec4(AuVec4 boundA, AuVec4 boundB) = 0; virtual AuVec4 NextVec4Sorted(AuVec4 min, AuVec4 max) = 0; virtual AuVecD2 NextVecD2(AuVecD2 boundA, AuVecD2 boundB) = 0; virtual AuVecD2 NextVecD2Sorted(AuVecD2 min, AuVecD2 max) = 0; virtual AuVecD3 NextVecD3(AuVecD3 boundA, AuVecD3 boundB) = 0; virtual AuVecD3 NextVecD3Sorted(AuVecD3 min, AuVecD3 max) = 0; virtual AuVecD4 NextVecD4(AuVecD4 boundA, AuVecD4 boundB) = 0; virtual AuVecD4 NextVecD4Sorted(AuVecD4 min, AuVecD4 max) = 0; virtual double NextDecimal() = 0; virtual double NextNumber(double dMin, double dMax) = 0; virtual AuUInt32 NextIndex(AuUInt32 uCount /* = max + 1*/) = 0; virtual uuids::uuid NextUUID() = 0; // Note: Fast arrays are deterministic with little seed entropy (usually 64bits, sometimes 32bits). // // Wont mitigate; use the slower non-fast variants if each numeric value (if not vec) OR // a *group* of N-components of each vector (if vec) need to be unique. // // Fast arrays simply rehash the previous bits to get the next component. While hopefully // perfectly uniform (otherwise the hash wouldn't be a good hash), it's entirely possible // to extrapolate the next value in the sequence. // // In addition, this applies to non-fast components of each vector; given an X component, // you can derive the Y and Z, even under non-fast functions. Fast vectors means the next // vector can be extrapolated from the previous group of vector components; nonfast, you // can only solve Y and Z. Fast vector arrays only have 64bits of entropy extrapolated to // 52bits * uCount * N bits of fully deterministic components; nonfast vector arrays have // 64bits * uCount bits of entropy, extrapolated to 52bits * uCount * N bits of partially // in-vector extrapolatable bits. // // Also note, it might not even be possible to extrapolate these components in practice. // This is because each component has some bits chucked away when shoving the seed into // the mantissa, and then each component gets manipulated using the same range provided // by the bound[..]s or min/max vecs parameters. Some bruteforce would be required. // // Wont add generics: if constexprs are very modern; we have slight differences between types; // generics would needs extra tags to handle memory view (near?) alloc-less // operations! Method is too ambigious compared to simple // unoverloaded and verbose/self-documenting method names. Also easier to bind // this way. virtual AuList NextArrayI32Range(AuUInt32 uCount, AuInt32 iMin, AuInt32 iMax) = 0; virtual AuList NextArrayI32RangeFast(AuUInt32 uCount, AuInt32 iMin, AuInt32 iMax) = 0; virtual AuList NextArrayU32Range(AuUInt32 uCount, AuUInt32 uMin, AuUInt32 uMax) = 0; virtual AuList NextArrayU32RangeFast(AuUInt32 uCount, AuUInt32 uMin, AuUInt32 uMax) = 0; virtual AuList NextArrayI64Range(AuUInt32 uCount, AuInt64 iMin, AuInt64 iMax) = 0; virtual AuList NextArrayI64RangeFast(AuUInt32 uCount, AuInt64 iMin, AuInt64 iMax) = 0; virtual AuList NextArrayU64Range(AuUInt32 uCount, AuUInt64 uMin, AuUInt64 uMax) = 0; virtual AuList NextArrayU64RangeFast(AuUInt32 uCount, AuUInt64 uMin, AuUInt64 uMax) = 0; virtual AuList NextArrayU32Mask(AuUInt32 uCount, AuUInt32 uMask) = 0; virtual AuList NextArrayU64Mask(AuUInt32 uCount, AuUInt64 uMask) = 0; virtual AuList NextArrayDoubleRange(AuUInt32 uCount, double dMin, double dMax) = 0; virtual AuList NextArrayDoubleRangeFast(AuUInt32 uCount, double dMin, double dMax) = 0; virtual AuList NextArrayI32(AuUInt32 uCount) = 0; virtual AuList NextArrayU32(AuUInt32 uCount) = 0; virtual AuList NextArrayI64(AuUInt32 uCount) = 0; virtual AuList NextArrayU64(AuUInt32 uCount) = 0; virtual AuList NextArrayVec2(AuUInt32 uCount, AuVec2 boundA, AuVec2 boundB) = 0; virtual AuList NextArrayVec2Fast(AuUInt32 uCount, AuVec2 boundA, AuVec2 boundB) = 0; virtual AuList NextArrayVec2Sorted(AuUInt32 uCount, AuVec2 min, AuVec2 max) = 0; virtual AuList NextArrayVec2SortedFast(AuUInt32 uCount, AuVec2 min, AuVec2 max) = 0; virtual AuList NextArrayVec3(AuUInt32 uCount, AuVec3 boundA, AuVec3 boundB) = 0; virtual AuList NextArrayVec3Fast(AuUInt32 uCount, AuVec3 boundA, AuVec3 boundB) = 0; virtual AuList NextArrayVec3Sorted(AuUInt32 uCount, AuVec3 min, AuVec3 max) = 0; virtual AuList NextArrayVec3SortedFast(AuUInt32 uCount, AuVec3 min, AuVec3 max) = 0; virtual AuList NextArrayVec4(AuUInt32 uCount, AuVec4 boundA, AuVec4 boundB) = 0; virtual AuList NextArrayVec4Fast(AuUInt32 uCount, AuVec4 boundA, AuVec4 boundB) = 0; virtual AuList NextArrayVec4Sorted(AuUInt32 uCount, AuVec4 min, AuVec4 max) = 0; virtual AuList NextArrayVec4SortedFast(AuUInt32 uCount, AuVec4 min, AuVec4 max) = 0; virtual AuList NextArrayVecD2(AuUInt32 uCount, AuVecD2 boundA, AuVecD2 boundB) = 0; virtual AuList NextArrayVecD2Fast(AuUInt32 uCount, AuVecD2 boundA, AuVecD2 boundB) = 0; virtual AuList NextArrayVecD2Sorted(AuUInt32 uCount, AuVecD2 min, AuVecD2 max) = 0; virtual AuList NextArrayVecD2SortedFast(AuUInt32 uCount, AuVecD2 min, AuVecD2 max) = 0; virtual AuList NextArrayVecD3(AuUInt32 uCount, AuVecD3 boundA, AuVecD3 boundB) = 0; virtual AuList NextArrayVecD3Fast(AuUInt32 uCount, AuVecD3 boundA, AuVecD3 boundB) = 0; virtual AuList NextArrayVecD3Sorted(AuUInt32 uCount, AuVecD3 min, AuVecD3 max) = 0; virtual AuList NextArrayVecD3SortedFast(AuUInt32 uCount, AuVecD3 min, AuVecD3 max) = 0; virtual AuList NextArrayVecD4(AuUInt32 uCount, AuVecD4 boundA, AuVecD4 boundB) = 0; virtual AuList NextArrayVecD4Fast(AuUInt32 uCount, AuVecD4 boundA, AuVecD4 boundB) = 0; virtual AuList NextArrayVecD4Sorted(AuUInt32 uCount, AuVecD4 min, AuVecD4 max) = 0; virtual AuList NextArrayVecD4SortedFast(AuUInt32 uCount, AuVecD4 min, AuVecD4 max) = 0; virtual AuList NextArrayDouble(AuUInt32 uCount) = 0; virtual AuList NextArrayDecimals(AuUInt32 uCount) = 0; virtual AuList NextArrayDecimalsFast(AuUInt32 uCount) = 0; virtual AuList NextArrayUUIDs(AuUInt32 uCount) = 0; virtual AuUInt NextArrayI32RangeInView(Memory::MemoryViewWrite write, AuInt32 iMin, AuInt32 iMax) = 0; virtual AuUInt NextArrayI32RangeFastInView(Memory::MemoryViewWrite write, AuInt32 iMin, AuInt32 iMax) = 0; virtual AuUInt NextArrayU32RangeInView(Memory::MemoryViewWrite write, AuUInt32 uMin, AuUInt32 uMax) = 0; virtual AuUInt NextArrayU32RangeFastInView(Memory::MemoryViewWrite write, AuUInt32 uMin, AuUInt32 uMax) = 0; virtual AuUInt NextArrayI64RangeInView(Memory::MemoryViewWrite write, AuInt64 iMin, AuInt64 iMax) = 0; virtual AuUInt NextArrayI64RangeFastInView(Memory::MemoryViewWrite write, AuInt64 iMin, AuInt64 iMax) = 0; virtual AuUInt NextArrayU64RangeInView(Memory::MemoryViewWrite write, AuUInt64 uMin, AuUInt64 uMax) = 0; virtual AuUInt NextArrayU64RangeFastInView(Memory::MemoryViewWrite write, AuUInt64 uMin, AuUInt64 uMax) = 0; virtual AuUInt NextArrayU32MaskInView(Memory::MemoryViewWrite write, AuUInt32 uMask) = 0; virtual AuUInt NextArrayU64MaskInView(Memory::MemoryViewWrite write, AuUInt64 uMask) = 0; virtual AuUInt NextArrayDoubleRangeInView(Memory::MemoryViewWrite write, double dMin, double dMax) = 0; virtual AuUInt NextArrayDoubleRangeFastInView(Memory::MemoryViewWrite write, double dMin, double dMax) = 0; virtual AuUInt NextArrayI32InView(Memory::MemoryViewWrite write) = 0; virtual AuUInt NextArrayU32InView(Memory::MemoryViewWrite write) = 0; virtual AuUInt NextArrayI64InView(Memory::MemoryViewWrite write) = 0; virtual AuUInt NextArrayU64InView(Memory::MemoryViewWrite write) = 0; virtual AuUInt NextArrayVec2InView(Memory::MemoryViewWrite write, AuVec2 boundA, AuVec2 boundB) = 0; virtual AuUInt NextArrayVec2FastInView(Memory::MemoryViewWrite write, AuVec2 boundA, AuVec2 boundB) = 0; virtual AuUInt NextArrayVec2SortedInView(Memory::MemoryViewWrite write, AuVec2 min, AuVec2 max) = 0; virtual AuUInt NextArrayVec2SortedFastInView(Memory::MemoryViewWrite write, AuVec2 min, AuVec2 max) = 0; virtual AuUInt NextArrayVec3InView(Memory::MemoryViewWrite write, AuVec3 boundA, AuVec3 boundB) = 0; virtual AuUInt NextArrayVec3FastInView(Memory::MemoryViewWrite write, AuVec3 boundA, AuVec3 boundB) = 0; virtual AuUInt NextArrayVec3SortedInView(Memory::MemoryViewWrite write, AuVec3 min, AuVec3 max) = 0; virtual AuUInt NextArrayVec3SortedFastInView(Memory::MemoryViewWrite write, AuVec3 min, AuVec3 max) = 0; virtual AuUInt NextArrayVec4InView(Memory::MemoryViewWrite write, AuVec4 boundA, AuVec4 boundB) = 0; virtual AuUInt NextArrayVec4FastInView(Memory::MemoryViewWrite write, AuVec4 boundA, AuVec4 boundB) = 0; virtual AuUInt NextArrayVec4SortedInView(Memory::MemoryViewWrite write, AuVec4 min, AuVec4 max) = 0; virtual AuUInt NextArrayVec4SortedFastInView(Memory::MemoryViewWrite write, AuVec4 min, AuVec4 max) = 0; virtual AuUInt NextArrayVecD2InView(Memory::MemoryViewWrite write, AuVecD2 boundA, AuVecD2 boundB) = 0; virtual AuUInt NextArrayVecD2FastInView(Memory::MemoryViewWrite write, AuVecD2 boundA, AuVecD2 boundB) = 0; virtual AuUInt NextArrayVecD2SortedInView(Memory::MemoryViewWrite write, AuVecD2 min, AuVecD2 max) = 0; virtual AuUInt NextArrayVecD2SortedFastInView(Memory::MemoryViewWrite write, AuVecD2 min, AuVecD2 max) = 0; virtual AuUInt NextArrayVecD3InView(Memory::MemoryViewWrite write, AuVecD3 boundA, AuVecD3 boundB) = 0; virtual AuUInt NextArrayVecD3FastInView(Memory::MemoryViewWrite write, AuVecD3 boundA, AuVecD3 boundB) = 0; virtual AuUInt NextArrayVecD3SortedInView(Memory::MemoryViewWrite write, AuVecD3 min, AuVecD3 max) = 0; virtual AuUInt NextArrayVecD3SortedFastInView(Memory::MemoryViewWrite write, AuVecD3 min, AuVecD3 max) = 0; virtual AuUInt NextArrayVecD4InView(Memory::MemoryViewWrite write, AuVecD4 boundA, AuVecD4 boundB) = 0; virtual AuUInt NextArrayVecD4FastInView(Memory::MemoryViewWrite write, AuVecD4 boundA, AuVecD4 boundB) = 0; virtual AuUInt NextArrayVecD4SortedInView(Memory::MemoryViewWrite write, AuVecD4 min, AuVecD4 max) = 0; virtual AuUInt NextArrayVecD4SortedFastInView(Memory::MemoryViewWrite write, AuVecD4 min, AuVecD4 max) = 0; virtual AuUInt NextArrayDoubleInView(Memory::MemoryViewWrite write) = 0; virtual AuUInt NextArrayDecimalsInView(Memory::MemoryViewWrite write) = 0; virtual AuUInt NextArrayDecimalsFastInView(Memory::MemoryViewWrite write) = 0; virtual AuUInt NextArrayUUIDsInView(Memory::MemoryViewWrite write) = 0; template inline void NextFillArray(T(&array)[N]) { Read(Memory::MemoryViewWrite(array)); } template inline void NextFillArray(T *pArray, AuUInt32 uCount) { Read(Memory::MemoryViewWrite(pArray, uCount * sizeof(T))); } template void NextFillRange(T &container) { NextFillArray(container.begin(), container.end() - container.begin()); } inline void NextFillBuffer(Memory::ByteBuffer &buffer) { auto view = buffer.GetNextLinearWrite(); NextFillRange(view); buffer.writePtr += view.length; } /** * @brief * @deprecated */ inline void NextFillRange(Memory::ByteBuffer &buffer) { NextFillBuffer(buffer); } template inline T NextFillTmpl() { T ret {}; Read(Memory::MemoryViewWrite(&ret, sizeof(T))); return ret; } template inline T NextIterator(T begin, T end) { auto nextItr = begin; auto uCount = std::distance(begin, end); std::advance(nextItr, NextIndex(uCount)); return nextItr; } template inline T &NextArray(T *pItems, AuUInt32 uCount) { return pItems[NextIndex(uCount)]; } template inline auto NextRange(T &items) { return NextIterator(items.begin(), items.end()); } template inline T &NextList(AuList &items) { return *NextRange(items); } template inline const T &NextList(const AuList &items) { return *NextRange(items); } template inline void ShuffleIterators(T begin, T end) { // Hitting TLS through the IAT is as dumb as throwing OOM to shuffle // DUMB either way AU_DEBUG_MEMCRUNCH; auto uCount = std::distance(begin, end); auto nextIndexArray = this->NextArrayU32RangeFast(uCount, 0, uCount - 1); for (AU_ITERATE_N(i, AuUInt(uCount))) { auto nextItrA = begin; auto nextItrB = begin; std::advance(nextItrA, i); std::advance(nextItrB, nextIndexArray[i]); AuSwap(*nextItrA, *nextItrB); } } template inline void ShuffleList(AuList &list) { this->ShuffleIterators(list.begin(), list.end()); } }; AUKN_SHARED_SOO2(Random, IRandomDevice, kSizeRNGDevice, ((const RandomDef &, def)), const RandomDef &def); }