iFarbod

MT Rand

Mar 8th, 2016
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.54 KB | None | 0 0
  1. // Minimalistic Mersenne Twister Engine
  2. // Author(s):       iFarbod <[email protected]>
  3. //
  4. // Copyright (c) 2014-2016 San Andreas Online
  5. // Use of this source code is governed by the MIT license that can be
  6. // found in the LICENSE file.
  7.  
  8. #pragma once
  9. #include <cstdint> // for int types
  10. #include <cstddef> // for size_t
  11.  
  12. #define PREVENT_MACRO_SUBSTITUTION
  13.  
  14. template<class UIntType,
  15.     size_t w, size_t n, size_t m, size_t r,
  16.     UIntType a, size_t u, UIntType d, size_t s,
  17.     UIntType b, size_t t,
  18.     UIntType c, size_t l, UIntType f>
  19. class MersenneTwister
  20. {
  21. public:
  22.     typedef UIntType result_type;
  23.  
  24.     static constexpr size_t word_size = w;
  25.     static constexpr size_t state_size = n;
  26.     static constexpr size_t shift_size = m;
  27.     static constexpr size_t mask_bits = r;
  28.     static constexpr UIntType xor_mask = a;
  29.     static constexpr size_t tempering_u = u;
  30.     static constexpr UIntType tempering_d = d;
  31.     static constexpr size_t tempering_s = s;
  32.     static constexpr UIntType tempering_b = b;
  33.     static constexpr size_t tempering_t = t;
  34.     static constexpr UIntType tempering_c = c;
  35.     static constexpr size_t tempering_l = l;
  36.     static constexpr UIntType initialization_multiplier = f;
  37.     static constexpr UIntType default_seed = 5489u;
  38.  
  39.     // backwards compatibility
  40.     static constexpr UIntType parameter_a = a;
  41.     static constexpr size_t output_u = u;
  42.     static constexpr size_t output_s = s;
  43.     static constexpr UIntType output_b = b;
  44.     static constexpr size_t output_t = t;
  45.     static constexpr UIntType output_c = c;
  46.     static constexpr size_t output_l = l;
  47.  
  48.     // old concept requirements
  49.     static constexpr bool has_fixed_range = false;
  50.  
  51.     MersenneTwister(UIntType _Seed = default_seed)
  52.     {
  53.         seed(_Seed);
  54.     }
  55.  
  56.     /**
  57.     * Sets the state x(0) to v mod 2w. Then, iteratively,
  58.     * sets x(i) to
  59.     * (i + f * (x(i-1) xor (x(i-1) rshift w-2))) mod 2<sup>w</sup>
  60.     * for i = 1 .. n-1. x(n) is the first value to be returned by operator().
  61.     */
  62.     void seed(const UIntType& value)
  63.     {
  64.         // New seeding algorithm from
  65.         // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
  66.         // In the previous versions, MSBs of the seed affected only MSBs of the
  67.         // state x[].
  68.         const UIntType mask = (max)();
  69.         x[0] = value & mask;
  70.         for (i = 1; i < n; i++) {
  71.             // See Knuth "The Art of Computer Programming"
  72.             // Vol. 2, 3rd ed., page 106
  73.             x[i] = (f * (x[i - 1] ^ (x[i - 1] >> (w - 2))) + i) & mask;
  74.         }
  75.  
  76.         normalize_state();
  77.     }
  78.  
  79.     void seed() { seed(default_seed); }
  80.  
  81.     /** Returns the smallest value that the generator can produce. */
  82.     static result_type min PREVENT_MACRO_SUBSTITUTION()
  83.     {
  84.         return 0;
  85.     }
  86.     /** Returns the largest value that the generator can produce. */
  87.     static result_type max PREVENT_MACRO_SUBSTITUTION()
  88.     {
  89.         return _WMSK;
  90.     }
  91.  
  92.     result_type operator()()
  93.     {
  94.         if (i == n)
  95.             twist();
  96.         // Step 4
  97.         UIntType z = x[i];
  98.         ++i;
  99.         z ^= ((z >> u) & d);
  100.         z ^= ((z << s) & b);
  101.         z ^= ((z << t) & c);
  102.         z ^= (z >> l);
  103.         return z;
  104.     }
  105.  
  106.     void discard(uintmax_t z)
  107.     {
  108.         for (uintmax_t j = 0; j < z; ++j) {
  109.             (*this)();
  110.         }
  111.     }
  112. private:
  113.     void twist()
  114.     {
  115.         const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
  116.         const UIntType lower_mask = ~upper_mask;
  117.  
  118.         const size_t unroll_factor = 6;
  119.         const size_t unroll_extra1 = (n - m) % unroll_factor;
  120.         const size_t unroll_extra2 = (m - 1) % unroll_factor;
  121.  
  122.         // split loop to avoid costly modulo operations
  123.         {  // extra scope for MSVC brokenness w.r.t. for scope
  124.             for (size_t j = 0; j < n - m - unroll_extra1; j++) {
  125.                 UIntType y = (x[j] & upper_mask) | (x[j + 1] & lower_mask);
  126.                 x[j] = x[j + m] ^ (y >> 1) ^ ((x[j + 1] & 1) * a);
  127.             }
  128.         }
  129.         {
  130.             for (size_t j = n - m - unroll_extra1; j < n - m; j++) {
  131.                 UIntType y = (x[j] & upper_mask) | (x[j + 1] & lower_mask);
  132.                 x[j] = x[j + m] ^ (y >> 1) ^ ((x[j + 1] & 1) * a);
  133.             }
  134.         }
  135.         {
  136.             for (size_t j = n - m; j < n - 1 - unroll_extra2; j++) {
  137.                 UIntType y = (x[j] & upper_mask) | (x[j + 1] & lower_mask);
  138.                 x[j] = x[j - (n - m)] ^ (y >> 1) ^ ((x[j + 1] & 1) * a);
  139.             }
  140.         }
  141.         {
  142.             for (size_t j = n - 1 - unroll_extra2; j < n - 1; j++) {
  143.                 UIntType y = (x[j] & upper_mask) | (x[j + 1] & lower_mask);
  144.                 x[j] = x[j - (n - m)] ^ (y >> 1) ^ ((x[j + 1] & 1) * a);
  145.             }
  146.         }
  147.         // last iteration
  148.         UIntType y = (x[n - 1] & upper_mask) | (x[0] & lower_mask);
  149.         x[n - 1] = x[m - 1] ^ (y >> 1) ^ ((x[0] & 1) * a);
  150.         i = 0;
  151.     }
  152.  
  153.     void normalize_state()
  154.     {
  155.         const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
  156.         const UIntType lower_mask = ~upper_mask;
  157.         UIntType y0 = x[m - 1] ^ x[n - 1];
  158.         if (y0 & (static_cast<UIntType>(1) << (w - 1))) {
  159.             y0 = ((y0 ^ a) << 1) | 1;
  160.         }
  161.         else {
  162.             y0 = y0 << 1;
  163.         }
  164.         x[0] = (x[0] & upper_mask) | (y0 & lower_mask);
  165.  
  166.         // fix up the state if it's all zeroes.
  167.         for (size_t j = 0; j < n; ++j) {
  168.             if (x[j] != 0) return;
  169.         }
  170.         x[0] = static_cast<UIntType>(1) << (w - 1);
  171.     }
  172.  
  173.     UIntType x[n];
  174.     size_t i;
  175.  
  176.     static constexpr UIntType _WMSK = ~((~UIntType(0) << (w - 1)) << 1);
  177.     static constexpr UIntType _HMSK = (_WMSK << r) & _WMSK;
  178.     static constexpr UIntType _LMSK = ~_HMSK & _WMSK;
  179. };
  180.  
  181. // Memory usage:
  182. // mt11213b   : 352 * sizeof(uint32_t) = 352 * 4 = 1408 bytes = ~1 KB
  183. // mt19937    : 625 * sizeof(uint32_t) = 625 * 4 = 2500 bytes = ~2 KB
  184. // mt19937_64 : 312 * sizeof(uint64_t) = 312 * 8 = 2496 bytes = ~2 KB
  185.  
  186. typedef MersenneTwister<uint32_t, 32, 351, 175, 19, 0xccab8ee7,
  187.     11, 0xffffffff, 7, 0x31b6ab00, 15, 0xffe50000, 17, 1812433253> MT11213b;
  188.  
  189. typedef MersenneTwister<uint32_t, 32, 624, 397, 31, 0x9908b0df,
  190.     11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1812433253> MT19937;
  191.  
  192. typedef MersenneTwister<uint64_t, 64, 312, 156, 31,
  193.     UINT64_C(0xb5026f5aa96619e9), 29, UINT64_C(0x5555555555555555), 17,
  194.     UINT64_C(0x71d67fffeda60000), 37, UINT64_C(0xfff7eee000000000), 43,
  195.     UINT64_C(6364136223846793005)> MT19937_64;
Advertisement
Add Comment
Please, Sign In to add comment