1 // =================================
 2 // Copyright (c) 2022 Seppo Laakko
 3 // Distributed under the MIT license
 4 // =================================
 5 
 6 namespace System
 7 {
 8     internal class MT
 9     {
10         public const int n = 624;
11         public const int m = 397;
12         public const uint matrixA = 0x9908b0dfu;
13         public const uint upperMask = 0x80000000u;
14         public const uint lowerMask = 0x7fffffffu;
15         public nothrow MT() : initialized(false)mti(0)mt()mag()
16         {
17         }
18         public inline nothrow bool Initialized()
19         {
20             return initialized;
21         }
22         public void InitWithRandomSeed()
23         {
24             uint seed = random_seed();
25             Init(seed);
26         }
27         public nothrow void Init(uint seed)
28         {
29             initialized = true;
30             mt[0] = seed;
31             for (mti = 1; mti < n; ++mti;)
32             {
33                 mt[mti] = 1812433253u * (mt[mti - 1] ^ (mt[mti - 1] >> 30u)) + cast<uint>(mti);
34             }
35             mag[0] = 0u;
36             mag[1] = matrixA;
37         }
38         public nothrow uint GenRand()
39         {
40             uint y = 0u;
41             if (mti >= n)
42             {
43                 int kk;
44                 for (kk = 0; kk < n - m; ++kk;)
45                 {
46                     y = (mt[kk] & upperMask) | (mt[kk + 1] & lowerMask);
47                     mt[kk] = mt[kk + m] ^ (y >> 1u) ^ mag[cast<int>(y & 0x01u)];
48                 }
49                 for (; kk < n - 1; ++kk;)
50                 {
51                     y = (mt[kk] & upperMask) | (mt[kk + 1] & lowerMask);
52                     mt[kk] = mt[kk + (m - n)] ^ (y >> 1u) ^ mag[cast<int>(y & 0x01u)];
53                 }
54                 y = (mt[n - 1] & upperMask) | (mt[0] & lowerMask);
55                 mt[n - 1] = mt[m - 1] ^ (y >> 1u) ^ mag[cast<int>(y & 0x01u)];
56                 mti = 0;
57             }
58             y = mt[mti++];
59             y = y ^ (y >> 11u);
60             y = y ^ ((y << 7u) & 0x9d2c5680u);
61             y = y ^ ((y << 15u) & 0xefc60000u);
62             y = y ^ (y >> 18u);
63             return y;
64         }
65         private bool initialized;
66         private int mti;
67         private uint[n] mt;
68         private uint[2] mag;
69     }
70     
71     private MT mt;
72     
73     public void InitRand(uint seed)
74     {
75         mt.Init(seed);
76     }
77     
78     public uint Random()
79     {
80         if (!mt.Initialized())
81         {
82             mt.InitWithRandomSeed();
83         }
84         return mt.GenRand();
85     }
86     
87     public ulong Random64()
88     {
89         return cast<ulong>(Random()) << 32u | cast<ulong>(Random());
90     }
91 }