-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
rand.py
59 lines (42 loc) · 1.35 KB
/
rand.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
import hashlib
import struct
MASK = 0xffffffff
class XorShift(object):
def __init__(self, seed=None):
self.state = [0] * 4
if seed is not None:
self.seed(seed)
def seed(self, seed):
bytes = hashlib.sha1(seed.encode("utf-8")).digest()
# 4 big endian integers, eg:
# (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | (x[3])
self.state[:] = struct.unpack(">IIII", bytes[:16])
def next_u32(self):
t = self.state[3]
s = self.state[0]
self.state[3] = self.state[2]
self.state[2] = self.state[1]
self.state[1] = s
t = (t << 11) & MASK
t ^= t >> 8
self.state[0] = (t ^ s ^ (s >> 19)) & MASK
return self.state[0]
def next(self):
self.next_u32() / MASK
def prandom(seed):
rand = XorShift(seed=seed)
return rand.next()
def test():
rand = XorShift(seed="wohoo")
assert rand.next_u32() == 3709882355
assert rand.next_u32() == 3406141351
assert rand.next_u32() == 2220835615
assert rand.next_u32() == 1978561524
assert rand.next_u32() == 2006162129
assert rand.next_u32() == 1526862107
assert rand.next_u32() == 2715875971
assert rand.next_u32() == 3524055327
assert rand.next_u32() == 1313248726
assert rand.next_u32() == 1591659718
if __name__ == '__main__':
test()