summary refs log tree commit diff stats
path: root/lib/pure/mersenne.nim
blob: afa343086cfe13329a2fb75edce87070e9b83172 (plain) (blame)
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
type
  MersenneTwister* = object
    mt: array[0..623, uint32]
    index: int

{.deprecated: [TMersenneTwister: MersenneTwister].}

proc newMersenneTwister*(seed: uint32): MersenneTwister =
  result.index = 0
  result.mt[0] = seed
  for i in 1..623'u32:
    result.mt[i] = (0x6c078965'u32 * (result.mt[i-1] xor (result.mt[i-1] shr 30'u32)) + i)

proc generateNumbers(m: var MersenneTwister) =
  for i in 0..623:
    var y = (m.mt[i] and 0x80000000'u32) +
            (m.mt[(i+1) mod 624] and 0x7fffffff'u32)
    m.mt[i] = m.mt[(i+397) mod 624] xor uint32(y shr 1'u32)
    if (y mod 2'u32) != 0:
      m.mt[i] = m.mt[i] xor 0x9908b0df'u32

proc getNum*(m: var MersenneTwister): uint32 =
  ## Returns the next pseudo random number ranging from 0 to high(uint32)
  if m.index == 0:
    generateNumbers(m)
  result = m.mt[m.index]
  m.index = (m.index + 1) mod m.mt.len

  result = result xor (result shr 11'u32)
  result = result xor ((7'u32 shl result) and 0x9d2c5680'u32)
  result = result xor ((15'u32 shl result) and 0xefc60000'u32)
  result = result xor (result shr 18'u32)

# Test
when not defined(testing) and isMainModule:
  var mt = newMersenneTwister(2525)

  for i in 0..99:
    echo mt.getNum