synthesizer-core-0.4: src/Synthesizer/RandomKnuth.hs
{- |
Very simple random number generator
which should be fast and should suffice for generating just noise.
<http://www.softpanorama.org/Algorithms/random_generators.shtml>
-}
module Synthesizer.RandomKnuth (T, cons, ) where
import qualified System.Random as R
newtype T = Cons Int
deriving Show
{-# INLINE cons #-}
cons :: Int -> T
cons = Cons
{-# INLINE factor #-}
factor :: Int
factor = 40692
{-# INLINE modulus #-}
modulus :: Int
modulus = 2147483399 -- 2^31-249
{-
We have to split the 32 bit integer in order to avoid overflow on multiplication.
'split' must be chosen, such that 'splitRem' is below 2^16.
-}
{-# INLINE split #-}
split :: Int
split = succ $ div modulus factor
{-# INLINE splitRem #-}
splitRem :: Int
splitRem = split * factor - modulus
instance R.RandomGen T where
{-# INLINE next #-}
next (Cons s) =
-- efficient computation of @mod (s*factor) modulus@ without Integer
let (sHigh, sLow) = divMod s split
in (s, Cons $ flip mod modulus $
splitRem*sHigh + factor*sLow)
{-# INLINE split #-}
split (Cons s) = (Cons (s*s), Cons (13+s))
{-# INLINE genRange #-}
genRange _ = (1, pred modulus)
{-
*Main> let s = 10000000000 in (next (Cons s), mod (fromIntegral s * fromIntegral factor) (fromIntegral modulus) :: Integer)
((1410065408,Cons 1920127854),1920127854)
-}