random.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "random.h"
  2. #include "entropy.h"
  3. #include "mersenne.h"
  4. #include <util/system/getpid.h>
  5. #include <util/thread/singleton.h>
  6. #include <util/stream/multi.h>
  7. #include <util/stream/mem.h>
  8. #include <util/digest/numeric.h>
  9. namespace {
  10. struct TProcStream {
  11. ui32 Extra;
  12. TMemoryInput MI;
  13. TMultiInput TI;
  14. static inline ui32 ExtraData() noexcept {
  15. ui32 data;
  16. EntropyPool().LoadOrFail(&data, sizeof(data));
  17. return IntHash(data ^ GetPID());
  18. }
  19. inline TProcStream() noexcept
  20. : Extra(ExtraData())
  21. , MI(&Extra, sizeof(Extra))
  22. , TI(&MI, &EntropyPool())
  23. {
  24. }
  25. inline IInputStream& S() noexcept {
  26. return TI;
  27. }
  28. };
  29. template <class T>
  30. struct TRndGen: public TMersenne<T> {
  31. inline TRndGen()
  32. : TMersenne<T>(TProcStream().S())
  33. {
  34. }
  35. inline TRndGen(T seed)
  36. : TMersenne<T>(seed)
  37. {
  38. }
  39. };
  40. template <class T>
  41. static inline TRndGen<T>* GetRndGen() {
  42. return FastTlsSingletonWithPriority<TRndGen<T>, 2>();
  43. }
  44. template <unsigned N>
  45. struct TToRealTypeBySize {
  46. using TResult = ui32;
  47. };
  48. template <>
  49. struct TToRealTypeBySize<8> {
  50. using TResult = ui64;
  51. };
  52. template <class T>
  53. struct TToRealType {
  54. using TResult = typename TToRealTypeBySize<sizeof(T)>::TResult;
  55. };
  56. }
  57. #define DEF_RND(TY) \
  58. template <> \
  59. TY RandomNumber<TY>() { \
  60. return GetRndGen<TToRealType<TY>::TResult>()->GenRand(); \
  61. } \
  62. \
  63. template <> \
  64. TY RandomNumber<TY>(TY n) { \
  65. return GetRndGen<TToRealType<TY>::TResult>()->Uniform(n); \
  66. }
  67. DEF_RND(char)
  68. DEF_RND(unsigned char)
  69. DEF_RND(unsigned int)
  70. DEF_RND(unsigned long)
  71. DEF_RND(unsigned short)
  72. DEF_RND(unsigned long long)
  73. #undef DEF_RND
  74. template <>
  75. bool RandomNumber<bool>() {
  76. return RandomNumber<ui8>() % 2 == 0;
  77. }
  78. template <>
  79. float RandomNumber<float>() {
  80. float ret;
  81. do {
  82. ret = (float)GetRndGen<ui64>()->GenRandReal2();
  83. } while (ret >= 1);
  84. return ret;
  85. }
  86. template <>
  87. double RandomNumber<double>() {
  88. return GetRndGen<ui64>()->GenRandReal4();
  89. }
  90. template <>
  91. long double RandomNumber<long double>() {
  92. return RandomNumber<double>();
  93. }
  94. void ResetRandomState() {
  95. *GetRndGen<ui32>() = TRndGen<ui32>();
  96. *GetRndGen<ui64>() = TRndGen<ui64>();
  97. }
  98. void SetRandomSeed(int seed) {
  99. *GetRndGen<ui32>() = TRndGen<ui32>(seed);
  100. *GetRndGen<ui64>() = TRndGen<ui64>(seed);
  101. }