common_ops.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #pragma once
  2. #include <util/system/defaults.h>
  3. #include <util/system/yassert.h>
  4. namespace NPrivate {
  5. constexpr double ToRandReal1(const ui32 x) noexcept {
  6. return x * (double)(1.0 / 4294967295.0);
  7. }
  8. constexpr double ToRandReal2(const ui32 x) noexcept {
  9. return x * (double)(1.0 / 4294967296.0);
  10. }
  11. constexpr double ToRandReal3(const ui32 x) noexcept {
  12. return ((double)x + 0.5) * (double)(1.0 / 4294967296.0);
  13. }
  14. constexpr double ToRandReal1(const ui64 x) noexcept {
  15. return (x >> 11) * (double)(1.0 / 9007199254740991.0);
  16. }
  17. constexpr double ToRandReal2(const ui64 x) noexcept {
  18. return (x >> 11) * (double)(1.0 / 9007199254740992.0);
  19. }
  20. constexpr double ToRandReal3(const ui64 x) noexcept {
  21. return ((x >> 12) + 0.5) * (double)(1.0 / 4503599627370496.0);
  22. }
  23. constexpr double ToRandReal4(const ui64 x) noexcept {
  24. return double(x * (double)(1.0 / 18446744073709551616.0L));
  25. }
  26. template <class T>
  27. static inline ui64 ToRand64(T&& rng, ui32 x) noexcept {
  28. return ((ui64)x) | (((ui64)rng.GenRand()) << 32);
  29. }
  30. template <class T>
  31. static constexpr ui64 ToRand64(T&&, ui64 x) noexcept {
  32. return x;
  33. }
  34. /*
  35. * return value in range [0, max) from any generator
  36. */
  37. template <class T, class TRandGen>
  38. static T GenUniform(T max, TRandGen&& gen) {
  39. Y_ABORT_UNLESS(max > 0, "Invalid random number range [0, 0)");
  40. const T randmax = gen.RandMax() - gen.RandMax() % max;
  41. T rand;
  42. while ((rand = gen.GenRand()) >= randmax) {
  43. /* no-op */
  44. }
  45. return rand % max;
  46. }
  47. } // namespace NPrivate
  48. template <class TRandType, class T>
  49. struct TCommonRNG {
  50. using TResult = TRandType;
  51. using result_type = TRandType;
  52. inline T& Engine() noexcept {
  53. return static_cast<T&>(*this);
  54. }
  55. static constexpr TResult _Min = TResult(0);
  56. static constexpr TResult _Max = TResult(-1);
  57. static constexpr TResult RandMax() noexcept {
  58. return _Max;
  59. }
  60. static constexpr TResult RandMin() noexcept {
  61. return _Min;
  62. }
  63. /* generates uniformly distributed random number on [0, t) interval */
  64. inline TResult Uniform(TResult t) noexcept {
  65. return ::NPrivate::GenUniform(t, Engine());
  66. }
  67. /* generates uniformly distributed random number on [f, t) interval */
  68. inline TResult Uniform(TResult f, TResult t) noexcept {
  69. return f + Uniform(t - f);
  70. }
  71. /* generates 64-bit random number for current(may be 32 bit) rng */
  72. inline ui64 GenRand64() noexcept {
  73. return ::NPrivate::ToRand64(Engine(), Engine().GenRand());
  74. }
  75. /* generates a random number on [0, 1]-real-interval */
  76. inline double GenRandReal1() noexcept {
  77. return ::NPrivate::ToRandReal1(Engine().GenRand());
  78. }
  79. /* generates a random number on [0, 1)-real-interval */
  80. inline double GenRandReal2() noexcept {
  81. return ::NPrivate::ToRandReal2(Engine().GenRand());
  82. }
  83. /* generates a random number on (0, 1)-real-interval */
  84. inline double GenRandReal3() noexcept {
  85. return ::NPrivate::ToRandReal3(Engine().GenRand());
  86. }
  87. /* generates a random number on [0, 1) with 53-bit resolution */
  88. inline double GenRandReal4() noexcept {
  89. return ::NPrivate::ToRandReal4(Engine().GenRand64());
  90. }
  91. // compatibility stuff
  92. inline TResult operator()() noexcept {
  93. return Engine().GenRand();
  94. }
  95. static constexpr TResult max() noexcept {
  96. return T::RandMax();
  97. }
  98. static constexpr TResult min() noexcept {
  99. return T::RandMin();
  100. }
  101. };