1 #include <soulng/util/Random.hpp>
  2 #if defined(_WIN32)
  3 #define _CRT_RAND_S
  4 #define WIN32_LEAN_AND_MEAN
  5 #include <windows.h>
  6 #else
  7 #include <unistd.h>
  8 #include <sys/types.h>
  9 #include <sys/stat.h>
 10 #include <fcntl.h>
 11 #endif
 12 #include <stdlib.h>
 13 #include <string.h>
 14 #include <stdio.h>
 15 
 16 namespace soulng { namespace util {
 17 
 18 #if defined(_WIN32)
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 #elif defined(__linux) || defined(__unix) || defined(__posix)
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 #else
 53 
 54 #error unknown platform
 55 
 56 #endif
 57 
 58 class MT 
 59 {
 60 private:
 61     static const int32_t n = 624;
 62     static const int32_t m = 397;
 63     static const uint32_t  matrixA = 0x9908b0dfu;
 64     static const uint32_t upperMask = 0x80000000u;
 65     static const uint32_t lowerMask = 0x7fffffffu;
 66 public:
 67     MT();
 68     bool Initialized()
 69     {
 70         return initialized;
 71     }
 72     void InitWithRandomSeed()
 73     {
 74         uint32_t seed = get_random_seed_from_system();
 75         Init(seed);
 76     }
 77     void Init(uint32_t seed)
 78     {
 79         initialized = true;
 80         mt[0] = seed;
 81         for (mti = 1; mti < n; ++mti)
 82         {
 83             mt[mti] = 1812433253u * (mt[mti - 1] ^ (mt[mti - 1] >> 30u)) + static_cast<uint32_t>(mti);
 84         }
 85         mag[0] = 0u;
 86         mag[1] = matrixA;
 87     }
 88     uint32_t GenRand()
 89     {
 90         uint32_t y = 0u;
 91         if (mti >= n)
 92         {
 93             int32_t kk;
 94             for (kk = 0; kk < n - m; ++kk)
 95             {
 96                 y = (mt[kk] & upperMask) | (mt[kk + 1] & lowerMask);
 97                 mt[kk] = mt[kk + m] ^ (y >> 1u) ^ mag[static_cast<int32_t>(y & 0x01u)];
 98             }
 99             for (; kk < n - 1; ++kk)
100             {
101                 y = (mt[kk] & upperMask) | (mt[kk + 1] & lowerMask);
102                 mt[kk] = mt[kk + (m - n)] ^ (y >> 1u) ^ mag[static_cast<int32_t>(y & 0x01u)];
103             }
104             y = (mt[n - 1] & upperMask) | (mt[0] & lowerMask);
105             mt[n - 1] = mt[m - 1] ^ (y >> 1u) ^ mag[static_cast<int32_t>(y & 0x01u)];
106             mti = 0;
107         }
108         y = mt[mti++];
109         y = y ^ (y >> 11u);
110         y = y ^ ((y << 7u) & 0x9d2c5680u);
111         y = y ^ ((y << 15u) & 0xefc60000u);
112         y = y ^ (y >> 18u);
113         return y;
114     }
115 private:
116     bool initialized;
117     int32_t mti;
118     uint32_t mt[n];
119     uint32_t mag[2];
120 };
121 
122 MT::MT() : initialized(false)mti(0)mt()mag()
123 {
124 }
125 
126 #ifdef _WIN32
127 
128 #else
129              MT* mt = nullptr;
130 #endif
131 
132 void InitMt(uint32_t seed)
133 {
134     if (mt == nullptr)
135     {
136         mt = new MT();
137     }
138     mt->Init(seed);
139 }
140 
141 uint32_t Random()
142 {
143     if (mt == nullptr)
144     {
145         mt = new MT();
146     }
147     if (!mt->Initialized())
148     {
149         mt->InitWithRandomSeed();
150     }
151     return mt->GenRand();
152 }
153 
154 uint64_t Random64()
155 {
156     return static_cast<uint64_t>(Random()) << 32 | static_cast<uint64_t>(Random());
157 }
158 
159 } } // namespace soulng::util