-
Notifications
You must be signed in to change notification settings - Fork 0
/
mad0.go
86 lines (70 loc) · 1.28 KB
/
mad0.go
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
package fastprng
import (
// "log"
// "encoding/binary"
)
type MaD0Source struct {
S []uint64
a uint64
b uint64
c uint64
d uint64
T []uint64
pos uint16
}
const Tlen = 512
func (mad *MaD0Source) Seed(seed int64) {
marcbb := NewMARCBB(seed)
mad.a = marcbb.UInt64()
mad.b = marcbb.UInt64()
mad.c = marcbb.UInt64()
mad.d = marcbb.UInt64()
mad.S = make([]uint64, len(marcbb.S))
for pos, val := range marcbb.S {
mad.S[pos] = uint64(val)
}
mad.T = make([]uint64, Tlen)
mad.pos = Tlen
}
func NewMaD0(seed int64) *MaD0Source {
mad := MaD0Source{}
mad.Seed(seed)
return &mad
}
func (r *MaD0Source) Generate() {
r.a = r.a + r.c
r.b = r.b + r.d
ta := r.a
tb := r.b
for i := 0; i <= 31; i++ {
r.c = r.c ^ (r.S[i] + r.a)
r.T[2*i] = r.c
r.c += (ta ^ tb)
r.d ^= (r.c + r.b)
// ta = ta <<< 3
ta = circular_shift_left(ta, 3)
r.d += (ta ^ tb)
r.T[(2*i)+1] = r.d
r.S[i] = r.d
// tb = tb >>> 5
tb = circular_shift_right(tb, 5)
}
}
func (r *MaD0Source) Next() uint64 {
if r.pos >= Tlen {
r.Generate()
r.pos = 0
}
data := r.T[r.pos]
r.pos++
return data
}
func (r *MaD0Source) Int63() int64 {
n := int64(r.Next())
n &= 0x7FFFFFFFFFFFFFFF
return n
}
func (r *MaD0Source) UInt64() uint64 {
n := uint64(r.Next())<<32 | uint64(r.Next())
return n
}