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 } }