mersenne.nim 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2015 Nim Contributors
  5. # See the file "copying.txt", included in this
  6. # distribution, for details about the copyright.
  7. ## The [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_Twister)
  8. ## random number generator.
  9. ## .. note:: The procs in this module work at compile-time.
  10. {.deprecated: "use `std/random` instead".}
  11. runnableExamples:
  12. var rand = newMersenneTwister(uint32.high) ## must be "var"
  13. doAssert rand.getNum() != rand.getNum() ## pseudorandom number
  14. ## See also
  15. ## ========
  16. ## * `random module<random.html>`_ for Nim's standard random number generator
  17. type
  18. MersenneTwister* = object
  19. ## The Mersenne Twister.
  20. mt: array[0..623, uint32]
  21. index: int
  22. proc newMersenneTwister*(seed: uint32): MersenneTwister =
  23. ## Creates a new `MersenneTwister` with seed `seed`.
  24. result.index = 0
  25. result.mt[0] = seed
  26. for i in 1'u32 .. 623'u32:
  27. result.mt[i] = (0x6c078965'u32 * (result.mt[i-1] xor
  28. (result.mt[i-1] shr 30'u32)) + i)
  29. proc generateNumbers(m: var MersenneTwister) =
  30. for i in 0..623:
  31. var y = (m.mt[i] and 0x80000000'u32) +
  32. (m.mt[(i+1) mod 624] and 0x7fffffff'u32)
  33. m.mt[i] = m.mt[(i+397) mod 624] xor uint32(y shr 1'u32)
  34. if (y mod 2'u32) != 0:
  35. m.mt[i] = m.mt[i] xor 0x9908b0df'u32
  36. proc getNum*(m: var MersenneTwister): uint32 =
  37. ## Returns the next pseudorandom `uint32`.
  38. if m.index == 0:
  39. generateNumbers(m)
  40. result = m.mt[m.index]
  41. m.index = (m.index + 1) mod m.mt.len
  42. result = result xor (result shr 11'u32)
  43. result = result xor ((result shl 7'u32) and 0x9d2c5680'u32)
  44. result = result xor ((result shl 15'u32) and 0xefc60000'u32)
  45. result = result xor (result shr 18'u32)