#include "random.h" #include "entropy.h" #include "mersenne.h" #include #include #include #include #include namespace { struct TProcStream { ui32 Extra; TMemoryInput MI; TMultiInput TI; static inline ui32 ExtraData() noexcept { ui32 data; EntropyPool().LoadOrFail(&data, sizeof(data)); return IntHash(data ^ GetPID()); } inline TProcStream() noexcept : Extra(ExtraData()) , MI(&Extra, sizeof(Extra)) , TI(&MI, &EntropyPool()) { } inline IInputStream& S() noexcept { return TI; } }; template struct TRndGen: public TMersenne { inline TRndGen() : TMersenne(TProcStream().S()) { } inline TRndGen(T seed) : TMersenne(seed) { } }; template static inline TRndGen* GetRndGen() { return FastTlsSingletonWithPriority, 2>(); } template struct TToRealTypeBySize { using TResult = ui32; }; template <> struct TToRealTypeBySize<8> { using TResult = ui64; }; template struct TToRealType { using TResult = typename TToRealTypeBySize::TResult; }; } #define DEF_RND(TY) \ template <> \ TY RandomNumber() { \ return GetRndGen::TResult>()->GenRand(); \ } \ \ template <> \ TY RandomNumber(TY n) { \ return GetRndGen::TResult>()->Uniform(n); \ } DEF_RND(char) DEF_RND(unsigned char) DEF_RND(unsigned int) DEF_RND(unsigned long) DEF_RND(unsigned short) DEF_RND(unsigned long long) #undef DEF_RND template <> bool RandomNumber() { return RandomNumber() % 2 == 0; } template <> float RandomNumber() { float ret; do { ret = (float)GetRndGen()->GenRandReal2(); } while (ret >= 1); return ret; } template <> double RandomNumber() { return GetRndGen()->GenRandReal4(); } template <> long double RandomNumber() { return RandomNumber(); } void ResetRandomState() { *GetRndGen() = TRndGen(); *GetRndGen() = TRndGen(); } void SetRandomSeed(int seed) { *GetRndGen() = TRndGen(seed); *GetRndGen() = TRndGen(seed); }