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