From 116e478a7d945f2012408c4d76fc9badbb257cd4 Mon Sep 17 00:00:00 2001 From: siddharth Date: Tue, 17 Aug 2021 20:15:17 -0400 Subject: lib: add MTRand type and methods This is going to replace MTSeed and MTExtract functions. --- lib/rng.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'lib/rng.go') diff --git a/lib/rng.go b/lib/rng.go index 7e7611e..6f57324 100644 --- a/lib/rng.go +++ b/lib/rng.go @@ -19,6 +19,13 @@ var mtCoefL uint32 = 18 var mtF uint32 = 1812433253 +// MT19937 instance struct +type MTRand struct { + genSt [624]uint32 + index uint32 + initialized bool +} + // Stores state of MT19937 generator. var mtGenSt []uint32 = make([]uint32, mtCoefN) var mtIndex uint32 = mtCoefN + 1 @@ -26,6 +33,16 @@ var mtIndex uint32 = mtCoefN + 1 var mtLowerMask uint32 = (1 << mtCoefR) - 1 var mtUpperMask uint32 = 0xFFFFFFFF & (^mtLowerMask) +func (r *MTRand) Seed(s uint32) { + r.index = mtCoefN + r.genSt[0] = s + for i := uint32(1); i < mtCoefN; i++ { + r.genSt[i] = (0xFFFFFFFF & + (mtF*(r.genSt[i-1]^(r.genSt[i-1]>>(mtCoefW-2))) + i)) + } + r.initialized = true +} + func MTSeed(seed uint32) { mtIndex = mtCoefN mtGenSt[0] = seed @@ -35,6 +52,26 @@ func MTSeed(seed uint32) { } } +func (r *MTRand) Extract() uint32 { + if !r.initialized || r.index >= mtCoefN { + if !r.initialized { + r.Seed(5489) + } + r.twist() + } + + y := r.genSt[r.index] + y = y ^ ((y >> mtCoefU) & mtCoefD) + y = y ^ ((y << mtCoefS) & mtCoefB) + y = y ^ ((y << mtCoefT) & mtCoefC) + y = y ^ (y >> mtCoefL) + + r.index = r.index + 1 + + y = 0xFFFFFFFF & y + return y +} + func MTExtract() uint32 { if mtIndex >= mtCoefN { if mtIndex > mtCoefN { @@ -55,6 +92,19 @@ func MTExtract() uint32 { return r } +func (r *MTRand) twist() { + for i := uint32(0); i < mtCoefN-1; i++ { + x := (r.genSt[i] & mtUpperMask) + + (r.genSt[(i+1)%mtCoefN] & mtLowerMask) + xA := x >> 1 + if x%2 != 0 { // lowest bit of x is 1 + xA = xA ^ mtCoefA + } + r.genSt[i] = r.genSt[(i+mtCoefM)%mtCoefN] ^ xA + } + r.index = 0 +} + func mtTwist() { for i := uint32(0); i < mtCoefN-1; i++ { x := (mtGenSt[i] & mtUpperMask) + -- cgit v1.2.3