mersenne64.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include "mersenne64.h"
  2. #include <util/generic/array_size.h>
  3. #include <util/stream/input.h>
  4. #define MM 156
  5. #define MATRIX_A ULL(0xB5026F5AA96619E9)
  6. #define UM ULL(0xFFFFFFFF80000000)
  7. #define LM ULL(0x7FFFFFFF)
  8. using namespace NPrivate;
  9. void TMersenne64::InitGenRand(ui64 seed) noexcept {
  10. mt[0] = seed;
  11. for (mti = 1; mti < NN; ++mti) {
  12. mt[mti] = (ULL(6364136223846793005) * (mt[mti - 1] ^ (mt[mti - 1] >> 62)) + mti);
  13. }
  14. }
  15. void TMersenne64::InitByArray(const ui64* init_key, size_t key_length) noexcept {
  16. ui64 i = 1;
  17. ui64 j = 0;
  18. ui64 k;
  19. InitGenRand(ULL(19650218));
  20. k = NN > key_length ? NN : key_length;
  21. for (; k; --k) {
  22. mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 62)) * ULL(3935559000370003845))) + init_key[j] + j;
  23. ++i;
  24. ++j;
  25. if (i >= NN) {
  26. mt[0] = mt[NN - 1];
  27. i = 1;
  28. }
  29. if (j >= key_length) {
  30. j = 0;
  31. }
  32. }
  33. for (k = NN - 1; k; --k) {
  34. mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 62)) * ULL(2862933555777941757))) - i;
  35. ++i;
  36. if (i >= NN) {
  37. mt[0] = mt[NN - 1];
  38. i = 1;
  39. }
  40. }
  41. mt[0] = ULL(1) << 63;
  42. }
  43. void TMersenne64::InitNext() noexcept {
  44. int i;
  45. ui64 x;
  46. ui64 mag01[2] = {
  47. ULL(0),
  48. MATRIX_A,
  49. };
  50. if (mti == NN + 1) {
  51. InitGenRand(ULL(5489));
  52. }
  53. for (i = 0; i < NN - MM; ++i) {
  54. x = (mt[i] & UM) | (mt[i + 1] & LM);
  55. mt[i] = mt[i + MM] ^ (x >> 1) ^ mag01[(int)(x & ULL(1))];
  56. }
  57. for (; i < NN - 1; ++i) {
  58. x = (mt[i] & UM) | (mt[i + 1] & LM);
  59. mt[i] = mt[i + (MM - NN)] ^ (x >> 1) ^ mag01[(int)(x & ULL(1))];
  60. }
  61. x = (mt[NN - 1] & UM) | (mt[0] & LM);
  62. mt[NN - 1] = mt[MM - 1] ^ (x >> 1) ^ mag01[(int)(x & ULL(1))];
  63. mti = 0;
  64. }
  65. TMersenne64::TMersenne64(IInputStream& input)
  66. : mti(NN + 1)
  67. {
  68. ui64 buf[128];
  69. input.LoadOrFail(buf, sizeof(buf));
  70. InitByArray(buf, Y_ARRAY_SIZE(buf));
  71. }
  72. #undef MM
  73. #undef MATRIX_A
  74. #undef UM
  75. #undef LM