-- |
-- Don't depend on any external source of psuedo-random numbers, because
-- we want to be able to save a psuedo-random seed and know that we can
-- generate the same psuedo-random sequence when we reload it.
--
module RNG
(randomIntegerStream,
randomIntegerStreamStream,
randomIntegerLine,
randomIntegerGrid)
where
import Data.List
import ListUtils
-- |
-- Generates the next in a sequence of psuedo-random Integers.
-- These numbers should not be used raw. (Due to insufficient
-- "random-ness" of the least significant bit.) Use a
-- randomIntegerStream[Stream].
--
nextRandomSeed :: Integer -> Integer
nextRandomSeed x = (x * 0x5DEECE66D + 0xB) `mod` (2^48)
-- |
-- A stream of random integers from a seed.
--
randomIntegerStream :: Integer -> [Integer]
randomIntegerStream x = let nri = nextRandomSeed x
in (nri `quot` 24) : (randomIntegerStream nri)
-- |
-- A stream of random integer streams. Good when you need to do
-- a lot of splitting.
--
randomIntegerStreamStream :: Integer -> [[Integer]]
randomIntegerStreamStream x = let nri1 = nextRandomSeed x
nri2 = nextRandomSeed nri1
in (randomIntegerStream (nri1 + 1) :
(randomIntegerStreamStream (nri2 - 1)))
-- |
-- An infinite (in both directions) sequence of random Integers, based
-- on a seed.
--
randomIntegerLine :: Integer -> (Integer -> Integer)
randomIntegerLine seed = bidirectionalAccessor1D $ randomIntegerStream seed
-- |
-- An infinite (in all directions) grid of random Integers, based
-- on a seed.
--
randomIntegerGrid :: Integer -> ((Integer,Integer) -> Integer)
randomIntegerGrid seed = bidirectionalAccessor2D $ map randomIntegerStream $ randomIntegerStream seed