mersenne32.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include "mersenne32.h"
  2. #include <util/generic/array_size.h>
  3. #include <util/stream/input.h>
  4. using namespace NPrivate;
  5. #define M 397
  6. #define MATRIX_A 0x9908b0dfUL
  7. #define UPPER_MASK 0x80000000UL
  8. #define LOWER_MASK 0x7fffffffUL
  9. void TMersenne32::InitGenRand(ui32 s) noexcept {
  10. mt[0] = s;
  11. for (mti = 1; mti < N; ++mti) {
  12. mt[mti] = (1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);
  13. }
  14. }
  15. void TMersenne32::InitByArray(const ui32 init_key[], size_t key_length) noexcept {
  16. InitGenRand(19650218UL);
  17. ui32 i = 1;
  18. ui32 j = 0;
  19. ui32 k = ui32(N > key_length ? N : key_length);
  20. for (; k; k--) {
  21. mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL)) + init_key[j] + j;
  22. ++i;
  23. ++j;
  24. if (i >= N) {
  25. mt[0] = mt[N - 1];
  26. i = 1;
  27. }
  28. if (j >= key_length) {
  29. j = 0;
  30. }
  31. }
  32. for (k = N - 1; k; k--) {
  33. mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941UL)) - i;
  34. ++i;
  35. if (i >= N) {
  36. mt[0] = mt[N - 1];
  37. i = 1;
  38. }
  39. }
  40. mt[0] = 0x80000000UL;
  41. }
  42. void TMersenne32::InitNext() noexcept {
  43. int kk;
  44. ui32 y;
  45. ui32 mag01[2] = {
  46. 0x0UL,
  47. MATRIX_A,
  48. };
  49. if (mti == N + 1) {
  50. InitGenRand(5489UL);
  51. }
  52. for (kk = 0; kk < N - M; ++kk) {
  53. y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
  54. mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
  55. }
  56. for (; kk < N - 1; ++kk) {
  57. y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
  58. mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
  59. }
  60. y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
  61. mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
  62. mti = 0;
  63. }
  64. TMersenne32::TMersenne32(IInputStream& input)
  65. : mti(N + 1)
  66. {
  67. ui32 buf[128];
  68. input.LoadOrFail(buf, sizeof(buf));
  69. InitByArray(buf, Y_ARRAY_SIZE(buf));
  70. }
  71. #undef M
  72. #undef MATRIX_A
  73. #undef UPPER_MASK
  74. #undef LOWER_MASK