sde-solver-0.1.0.0: src/Numeric/DSDE/RNG.hs
{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances,
TypeFamilies, IncoherentInstances, ConstraintKinds,
FunctionalDependencies, BangPatterns #-}
module Numeric.DSDE.RNG where
import Control.Applicative
import Control.Monad.Identity
import Control.Monad.ST
import Control.Monad.State
import Data.Maybe
import qualified Data.Random.Normal as NORMAL
import qualified Data.Vector.Unboxed as V
import qualified System.Random.Mersenne.Pure64 as MT
import Numeric.DSDE.SDE (Parameter)
import qualified System.Random.MWC as MWC
import qualified System.Random.MWC.Distributions as MD
-- | Default seed used by instances when the 'initialize' method is provided with 'Nothing'.
defaultSeed :: Int
defaultSeed = 0
-- | Typeclass describing a PRNG working in some monad 'm' and generating values of type 'p'.
class (Monad m, Functor m, Parameter p) => RNGGen g m p | g m -> p where
-- | Generate a N(0,1) random number using the supplied generator.
getRand :: g -> m p
-- | Initialize a generator using some seed or defaulting to a constant.
initialize :: Maybe Int -> m g
-- | 'RNGGen' instance for the ST-monadic MWC RNG.
instance RNGGen (MWC.Gen s) (ST s) Double where
getRand = MD.normal 0 1
initialize s = MWC.initialize . V.singleton . fromIntegral $ fromMaybe defaultSeed s
-- | 'RNGGen' instance for the IO-monadic MWC RNG.
instance (MWC.GenIO ~ d) => RNGGen d IO Double where
{-# INLINE getRand #-}
getRand = MD.normal 0 1
{-# INLINE initialize #-}
initialize (Just n) = MWC.initialize . V.singleton . fromIntegral $ n
initialize Nothing = MWC.withSystemRandom . MWC.asGenIO $ return
-- | 'RNGGen' instance for the pure monadic Mersenne Twister RNG, operating in monad 'State'.
instance RNGGen MT.PureMT (State MT.PureMT) Double where
{-# INLINE getRand #-}
getRand _ = do
!(sample, gen') <- NORMAL.normal <$> get
put gen'
return sample
{-# INLINE initialize #-}
initialize = return . MT.pureMT . fromIntegral . fromMaybe defaultSeed