This repository has been archived by the owner on Oct 19, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathMersenneTwister.py
178 lines (152 loc) · 5.6 KB
/
MersenneTwister.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# from _typeshed import Self
from typing import List
import time
from math import floor
double = float
_int = int
class uint(_int):
def __new__(cls, value):
return value & 0xFFFFFFFF
class MersenneTwister:
# Class MersenneTwister generates random numbers
# from a uniform distribution using the Mersenne
# Twister algorithm.
N: int = 624
M: int = 397
MATRIX_A: uint = 0x9908B0DF
UPPER_MASK: uint = 0x80000000
LOWER_MASK: uint = 0x7FFFFFFF
MAX_RAND_INT: int = 0x7FFFFFFF
mag01: List[uint] = [0x0, MATRIX_A]
mt: List[uint] = [0] * N
mti: int = N + 1
def __init__(self, seed: int = None) -> None:
if seed == None:
seed = time.timens()
self.init_genrand(uint(seed))
# public MersenneTwister(int[] init)
# {
# uint[] initArray = new uint[init.Length];
# for (int i = 0; i < init.Length; ++i)
# initArray[i] = (uint)init[i];
# init_by_array(initArray, (uint)initArray.Length);
# }
MaxRandomInt: int = 0x7FFFFFFF
def Next(self, minValue: int = None, maxValue: int = None) -> int:
if minValue == None:
if maxValue == None:
return self.genrand_int31()
minValue = 0
if minValue > maxValue:
minValue, maxValue = maxValue, minValue
return int(floor((maxValue - minValue + 1) * self.genrand_real1() + minValue))
def NextFloat(self, includeOne: bool = False) -> float:
if includeOne:
return float(self.genrand_real1())
return float(self.genrand_real2())
def NextFloatPositive(self) -> float:
return float(self.genrand_real3())
def NextDouble(self, includeOne: bool = False) -> double:
if includeOne:
return self.genrand_real(1)
return self.genrand_real2()
def NextDoublePositive(self) -> double:
return self.genrand_real3()
def Next53BitRes(self):
return self.genrand_res53()
def NextBytes(self, length: int) -> bytes:
return b"".join(
self.genrand_int31().to_bytes(4, "little", signed=False)
for _ in range(0, length, 4)
)[:length]
# public void Initialize()
# { init_genrand((uint)DateTime.Now.Millisecond); }
# public void Initialize(int seed)
# { init_genrand((uint)seed); }
# public void Initialize(int[] init)
# {
# uint[] initArray = new uint[init.Length];
# for (int i = 0; i < init.Length; ++i)
# initArray[i] = (uint)init[i];
# init_by_array(initArray, (uint)initArray.Length);
# }
def init_genrand(self, s: uint) -> None:
self.mt[0] = s & 0xFFFFFFFF
for mti in range(1, self.N):
self.mt[mti] = (
uint(1812433253 * (self.mt[mti - 1] ^ (self.mt[mti - 1] >> 30)) + mti)
& 0xFFFFFFFF
)
self.mti = self.N
# private void init_by_array(uint[] init_key, uint key_length)
# {
# int i, j, k;
# init_genrand(19650218U);
# i = 1; j = 0;
# k = (int)(N > key_length ? N : key_length);
# for (; k > 0; k--)
# {
# mt[i] = (uint)((uint)(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525U)) + init_key[j] + j);
# mt[i] &= 0xffffffffU;
# i++; j++;
# if (i >= N) { mt[0] = mt[N - 1]; i = 1; }
# if (j >= key_length) j = 0;
# }
# for (k = N - 1; k > 0; k--)
# {
# mt[i] = (uint)((uint)(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) *
# 1566083941U)) - i);
# mt[i] &= 0xffffffffU;
# i++;
# if (i >= N) { mt[0] = mt[N - 1]; i = 1; }
# }
# mt[0] = 0x80000000U;
# }
def genrand_int32(self) -> uint:
y: uint
if self.mti >= self.N:
kk: int
if self.mti == self.N + 1:
self.init_genrand(5489)
for kk in range(self.N - self.M):
y = uint(
(self.mt[kk] & self.UPPER_MASK)
| (self.mt[kk + 1] & self.LOWER_MASK)
)
self.mt[kk] = uint(
self.mt[kk + self.M] ^ (y >> 1) ^ self.mag01[y & 0x1]
)
for kk in range(self.N - self.M, self.N - 1):
y = uint(
(self.mt[kk] & self.UPPER_MASK)
| (self.mt[kk + 1] & self.LOWER_MASK)
)
self.mt[kk] = uint(
self.mt[kk + (self.M - self.N)] ^ (y >> 1) ^ self.mag01[y & 0x1]
)
y = uint(
(self.mt[self.N - 1] & self.UPPER_MASK) | (self.mt[0] & self.LOWER_MASK)
)
self.mt[self.N - 1] = uint(
self.mt[self.M - 1] ^ (y >> 1) ^ self.mag01[y & 0x1]
)
self.mti = 0
y = self.mt[self.mti]
self.mti += 1
y = uint(y ^ (y >> 11))
y = uint(y ^ ((y << 7) & 0x9D2C5680))
y = uint(y ^ ((y << 15) & 0xEFC60000))
y = uint(y ^ (y >> 18))
return y
def genrand_int31(self) -> int:
return int(self.genrand_int32() >> 1)
def genrand_real1(self) -> double:
return self.genrand_int32() * (1.0 / 4294967295.0)
def genrand_real2(self) -> double:
return self.genrand_int32() * (1.0 / 4294967296.0)
def genrand_real3(self) -> double:
return (double(self.genrand_int32()) + 0.5) * (1.0 / 4294967296.0)
def genrand_res53(self):
a = uint(self.genrand_int32() >> 5)
b = uint(self.genrand_int32() >> 6)
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0)