{-# LANGUAGE RankNTypes #-}

-- |
-- Module     : Simulation.Aivika.Generator
-- Copyright  : Copyright (c) 2009-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 8.0.1
--
-- Below is defined a type class of the random number generator.
--
module Simulation.Aivika.Generator 
       (Generator(..),
        GeneratorType(..),
        DiscretePDF(..),
        newGenerator,
        newRandomGenerator,
        newRandomGenerator01) where

import System.Random
import qualified System.Random.MWC as MWC
import Data.IORef
import Data.Word
import Data.Vector
import Data.Functor

-- | A discrete probability density function.
type DiscretePDF a = [(a, Double)]

-- | Defines a random number generator.
data Generator =
  Generator { Generator -> Double -> Double -> IO Double
generateUniform :: Double -> Double -> IO Double,
              -- ^ Generate an uniform random number
              -- with the specified minimum and maximum.
              Generator -> Int -> Int -> IO Int
generateUniformInt :: Int -> Int -> IO Int,
              -- ^ Generate an uniform integer random number
              -- with the specified minimum and maximum.
              Generator -> Double -> Double -> Double -> IO Double
generateTriangular :: Double -> Double -> Double -> IO Double,
              -- ^ Generate a triangular random number
              -- by the specified minimum, median and maximum.
              Generator -> Double -> Double -> IO Double
generateNormal :: Double -> Double -> IO Double,
              -- ^ Generate the normal random number
              -- with the specified mean and deviation.
              Generator -> Double -> Double -> IO Double
generateLogNormal :: Double -> Double -> IO Double,
              -- ^ Generate a random number from the lognormal distribution derived
              -- from a normal distribution with the specified mean and deviation.
              Generator -> Double -> IO Double
generateExponential :: Double -> IO Double,
              -- ^ Generate the random number distributed exponentially
              -- with the specified mean (the reciprocal of the rate).
              Generator -> Double -> Int -> IO Double
generateErlang :: Double -> Int -> IO Double,
              -- ^ Generate the Erlang random number
              -- with the specified scale (the reciprocal of the rate) and integer shape.
              Generator -> Double -> IO Int
generatePoisson :: Double -> IO Int,
              -- ^ Generate the Poisson random number
              -- with the specified mean.
              Generator -> Double -> Int -> IO Int
generateBinomial :: Double -> Int -> IO Int,
              -- ^ Generate the binomial random number
              -- with the specified probability and number of trials.
              Generator -> Double -> Double -> IO Double
generateGamma :: Double -> Double -> IO Double,
              -- ^ Generate a random number from the Gamma distribution with
              -- the specified shape (kappa) and scale (theta, a reciprocal of the rate).
              --
              -- The probability density for the Gamma distribution is
              --
              -- @f x = x ** (kappa - 1) * exp (- x \/ theta) \/ theta ** kappa * Gamma kappa@
              Generator -> Double -> Double -> IO Double
generateBeta :: Double -> Double -> IO Double,
              -- ^ Generate a random number from the Beta distribution by
              -- the specified shape parameters (alpha and beta).
              --
              -- The probability density for the Beta distribution is
              --
              -- @f x = x ** (alpha - 1) * (1 - x) ** (beta - 1) \/ B alpha beta@
              Generator -> Double -> Double -> IO Double
generateWeibull :: Double -> Double -> IO Double,
              -- ^ Generate a random number from the Weibull distribution by
              -- the specified shape and scale.
              Generator -> forall a. DiscretePDF a -> IO a
generateDiscrete :: forall a. DiscretePDF a -> IO a,
              -- ^ Generate a random value from the specified discrete distribution.
              Generator -> IO Int
generateSequenceNo :: IO Int
              -- ^ Generate a sequence number which can be considered quite unique.
            }

-- | Generate the uniform random number with the specified minimum and maximum.
generateUniform01 :: IO Double
                     -- ^ the generator
                     -> Double
                     -- ^ minimum
                     -> Double
                     -- ^ maximum
                     -> IO Double
generateUniform01 :: IO Double -> Double -> Double -> IO Double
generateUniform01 IO Double
g Double
min Double
max =
  do Double
x <- IO Double
g
     forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
min forall a. Num a => a -> a -> a
+ Double
x forall a. Num a => a -> a -> a
* (Double
max forall a. Num a => a -> a -> a
- Double
min)

-- | Generate the uniform random number with the specified minimum and maximum.
generateUniformInt01 :: IO Double
                        -- ^ the generator
                        -> Int
                        -- ^ minimum
                        -> Int
                        -- ^ maximum
                        -> IO Int
generateUniformInt01 :: IO Double -> Int -> Int -> IO Int
generateUniformInt01 IO Double
g Int
min Int
max =
  do Double
x <- IO Double
g
     let min' :: Double
min' = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
min forall a. Num a => a -> a -> a
- Double
0.5
         max' :: Double
max' = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
max forall a. Num a => a -> a -> a
+ Double
0.5
         z :: Int
z    = forall a b. (RealFrac a, Integral b) => a -> b
round (Double
min' forall a. Num a => a -> a -> a
+ Double
x forall a. Num a => a -> a -> a
* (Double
max' forall a. Num a => a -> a -> a
- Double
min'))
         z' :: Int
z'   = if Int
z forall a. Ord a => a -> a -> Bool
< Int
min
                then Int
min
                else if Int
z forall a. Ord a => a -> a -> Bool
> Int
max
                     then Int
max
                     else Int
z
     forall (m :: * -> *) a. Monad m => a -> m a
return Int
z'

-- | Generate the triangular random number by the specified minimum, median and maximum.
generateTriangular01 :: IO Double
                        -- ^ the generator
                        -> Double
                        -- ^ minimum
                        -> Double
                        -- ^ median
                        -> Double
                        -- ^ maximum
                        -> IO Double
generateTriangular01 :: IO Double -> Double -> Double -> Double -> IO Double
generateTriangular01 IO Double
g Double
min Double
median Double
max =
  do Double
x <- IO Double
g
     if Double
x forall a. Ord a => a -> a -> Bool
<= (Double
median forall a. Num a => a -> a -> a
- Double
min) forall a. Fractional a => a -> a -> a
/ (Double
max forall a. Num a => a -> a -> a
- Double
min)
       then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
min forall a. Num a => a -> a -> a
+ forall a. Floating a => a -> a
sqrt ((Double
median forall a. Num a => a -> a -> a
- Double
min) forall a. Num a => a -> a -> a
* (Double
max forall a. Num a => a -> a -> a
- Double
min) forall a. Num a => a -> a -> a
* Double
x)
       else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
max forall a. Num a => a -> a -> a
- forall a. Floating a => a -> a
sqrt ((Double
max forall a. Num a => a -> a -> a
- Double
median) forall a. Num a => a -> a -> a
* (Double
max forall a. Num a => a -> a -> a
- Double
min) forall a. Num a => a -> a -> a
* (Double
1 forall a. Num a => a -> a -> a
- Double
x))

-- | Create a normal random number generator with mean 0 and variance 1
-- by the specified generator of uniform random numbers from 0 to 1.
newNormalGenerator01 :: IO Double
                        -- ^ the generator
                        -> IO (IO Double)
newNormalGenerator01 :: IO Double -> IO (IO Double)
newNormalGenerator01 IO Double
g =
  do IORef Double
nextRef <- forall a. a -> IO (IORef a)
newIORef Double
0.0
     IORef Bool
flagRef <- forall a. a -> IO (IORef a)
newIORef Bool
False
     IORef Double
xi1Ref  <- forall a. a -> IO (IORef a)
newIORef Double
0.0
     IORef Double
xi2Ref  <- forall a. a -> IO (IORef a)
newIORef Double
0.0
     IORef Double
psiRef  <- forall a. a -> IO (IORef a)
newIORef Double
0.0
     let loop :: IO ()
loop =
           do Double
psi <- forall a. IORef a -> IO a
readIORef IORef Double
psiRef
              if (Double
psi forall a. Ord a => a -> a -> Bool
>= Double
1.0) Bool -> Bool -> Bool
|| (Double
psi forall a. Eq a => a -> a -> Bool
== Double
0.0)
                then do Double
g1 <- IO Double
g
                        Double
g2 <- IO Double
g
                        let xi1 :: Double
xi1 = Double
2.0 forall a. Num a => a -> a -> a
* Double
g1 forall a. Num a => a -> a -> a
- Double
1.0
                            xi2 :: Double
xi2 = Double
2.0 forall a. Num a => a -> a -> a
* Double
g2 forall a. Num a => a -> a -> a
- Double
1.0
                            psi :: Double
psi = Double
xi1 forall a. Num a => a -> a -> a
* Double
xi1 forall a. Num a => a -> a -> a
+ Double
xi2 forall a. Num a => a -> a -> a
* Double
xi2
                        forall a. IORef a -> a -> IO ()
writeIORef IORef Double
xi1Ref Double
xi1
                        forall a. IORef a -> a -> IO ()
writeIORef IORef Double
xi2Ref Double
xi2
                        forall a. IORef a -> a -> IO ()
writeIORef IORef Double
psiRef Double
psi
                        IO ()
loop
                else forall a. IORef a -> a -> IO ()
writeIORef IORef Double
psiRef forall a b. (a -> b) -> a -> b
$ forall a. Floating a => a -> a
sqrt (- Double
2.0 forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
log Double
psi forall a. Fractional a => a -> a -> a
/ Double
psi)
     forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
       do Bool
flag <- forall a. IORef a -> IO a
readIORef IORef Bool
flagRef
          if Bool
flag
            then do forall a. IORef a -> a -> IO ()
writeIORef IORef Bool
flagRef Bool
False
                    forall a. IORef a -> IO a
readIORef IORef Double
nextRef
            else do forall a. IORef a -> a -> IO ()
writeIORef IORef Double
xi1Ref Double
0.0
                    forall a. IORef a -> a -> IO ()
writeIORef IORef Double
xi2Ref Double
0.0
                    forall a. IORef a -> a -> IO ()
writeIORef IORef Double
psiRef Double
0.0
                    IO ()
loop
                    Double
xi1 <- forall a. IORef a -> IO a
readIORef IORef Double
xi1Ref
                    Double
xi2 <- forall a. IORef a -> IO a
readIORef IORef Double
xi2Ref
                    Double
psi <- forall a. IORef a -> IO a
readIORef IORef Double
psiRef
                    forall a. IORef a -> a -> IO ()
writeIORef IORef Bool
flagRef Bool
True
                    forall a. IORef a -> a -> IO ()
writeIORef IORef Double
nextRef forall a b. (a -> b) -> a -> b
$ Double
xi2 forall a. Num a => a -> a -> a
* Double
psi
                    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
xi1 forall a. Num a => a -> a -> a
* Double
psi

-- | Return the exponential random number with the specified mean.
generateExponential01 :: IO Double
                         -- ^ the generator
                         -> Double
                         -- ^ the mean
                         -> IO Double
generateExponential01 :: IO Double -> Double -> IO Double
generateExponential01 IO Double
g Double
mu =
  do Double
x <- IO Double
g
     forall (m :: * -> *) a. Monad m => a -> m a
return (- forall a. Floating a => a -> a
log Double
x forall a. Num a => a -> a -> a
* Double
mu)

-- | Return the Erlang random number.
generateErlang01 :: IO Double
                    -- ^ the generator
                    -> Double
                    -- ^ the scale
                    -> Int
                    -- ^ the shape
                    -> IO Double
generateErlang01 :: IO Double -> Double -> Int -> IO Double
generateErlang01 IO Double
g Double
beta Int
m =
  do Double
x <- forall {t}. (Ord t, Num t) => t -> Double -> IO Double
loop Int
m Double
1
     forall (m :: * -> *) a. Monad m => a -> m a
return (- forall a. Floating a => a -> a
log Double
x forall a. Num a => a -> a -> a
* Double
beta)
       where loop :: t -> Double -> IO Double
loop t
m Double
acc
               | t
m forall a. Ord a => a -> a -> Bool
< t
0     = forall a. HasCallStack => [Char] -> a
error [Char]
"Negative shape: generateErlang."
               | t
m forall a. Eq a => a -> a -> Bool
== t
0    = forall (m :: * -> *) a. Monad m => a -> m a
return Double
acc
               | Bool
otherwise = do Double
x <- IO Double
g
                                t -> Double -> IO Double
loop (t
m forall a. Num a => a -> a -> a
- t
1) (Double
x forall a. Num a => a -> a -> a
* Double
acc)

-- | Generate the Poisson random number with the specified mean.
generatePoisson01 :: IO Double
                     -- ^ the generator
                     -> Double
                     -- ^ the mean
                     -> IO Int
generatePoisson01 :: IO Double -> Double -> IO Int
generatePoisson01 IO Double
g Double
mu =
  do Double
prob0 <- IO Double
g
     let loop :: Double -> Double -> t -> m t
loop Double
prob Double
prod t
acc
           | Double
prob forall a. Ord a => a -> a -> Bool
<= Double
prod = forall (m :: * -> *) a. Monad m => a -> m a
return t
acc
           | Bool
otherwise    = Double -> Double -> t -> m t
loop
                            (Double
prob forall a. Num a => a -> a -> a
- Double
prod)
                            (Double
prod forall a. Num a => a -> a -> a
* Double
mu forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (t
acc forall a. Num a => a -> a -> a
+ t
1))
                            (t
acc forall a. Num a => a -> a -> a
+ t
1)
     forall {m :: * -> *} {t}.
(Monad m, Integral t) =>
Double -> Double -> t -> m t
loop Double
prob0 (forall a. Floating a => a -> a
exp (- Double
mu)) Int
0

-- | Generate a binomial random number with the specified probability and number of trials. 
generateBinomial01 :: IO Double
                      -- ^ the generator
                      -> Double 
                      -- ^ the probability
                      -> Int
                      -- ^ the number of trials
                      -> IO Int
generateBinomial01 :: IO Double -> Double -> Int -> IO Int
generateBinomial01 IO Double
g Double
prob Int
trials = forall {t} {t}. (Ord t, Num t, Num t) => t -> t -> IO t
loop Int
trials Int
0 where
  loop :: t -> t -> IO t
loop t
n t
acc
    | t
n forall a. Ord a => a -> a -> Bool
< t
0     = forall a. HasCallStack => [Char] -> a
error [Char]
"Negative number of trials: generateBinomial."
    | t
n forall a. Eq a => a -> a -> Bool
== t
0    = forall (m :: * -> *) a. Monad m => a -> m a
return t
acc
    | Bool
otherwise = do Double
x <- IO Double
g
                     if Double
x forall a. Ord a => a -> a -> Bool
<= Double
prob
                       then t -> t -> IO t
loop (t
n forall a. Num a => a -> a -> a
- t
1) (t
acc forall a. Num a => a -> a -> a
+ t
1)
                       else t -> t -> IO t
loop (t
n forall a. Num a => a -> a -> a
- t
1) t
acc

-- | Generate a random number from the Gamma distribution using Marsaglia and Tsang method.
generateGamma01 :: IO Double
                   -- ^ a normal random number ~ N (0,1)
                   -> IO Double
                   -- ^ an uniform random number ~ U (0, 1)
                   -> Double
                   -- ^ the shape parameter (kappa) 
                   -> Double
                   -- ^ the scale parameter (theta)
                   -> IO Double
generateGamma01 :: IO Double -> IO Double -> Double -> Double -> IO Double
generateGamma01 IO Double
gn IO Double
gu Double
kappa Double
theta
  | Double
kappa forall a. Ord a => a -> a -> Bool
<= Double
0 = forall a. HasCallStack => [Char] -> a
error [Char]
"The shape parameter (kappa) must be positive: generateGamma01"
  | Double
kappa forall a. Ord a => a -> a -> Bool
> Double
1  =
    let d :: Double
d = Double
kappa forall a. Num a => a -> a -> a
- Double
1 forall a. Fractional a => a -> a -> a
/ Double
3
        c :: Double
c = Double
1 forall a. Fractional a => a -> a -> a
/ forall a. Floating a => a -> a
sqrt (Double
9 forall a. Num a => a -> a -> a
* Double
d)
        loop :: IO Double
loop =
          do Double
z <- IO Double
gn
             if Double
z forall a. Ord a => a -> a -> Bool
<= - (Double
1 forall a. Fractional a => a -> a -> a
/ Double
c)
               then IO Double
loop
               else do let v :: Double
v = (Double
1 forall a. Num a => a -> a -> a
+ Double
c forall a. Num a => a -> a -> a
* Double
z) forall a. Floating a => a -> a -> a
** Double
3
                       Double
u <- IO Double
gu
                       if forall a. Floating a => a -> a
log Double
u forall a. Ord a => a -> a -> Bool
> Double
0.5 forall a. Num a => a -> a -> a
* Double
z forall a. Num a => a -> a -> a
* Double
z forall a. Num a => a -> a -> a
+ Double
d forall a. Num a => a -> a -> a
- Double
d forall a. Num a => a -> a -> a
* Double
v forall a. Num a => a -> a -> a
+ Double
d forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
log Double
v
                         then IO Double
loop
                         else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
d forall a. Num a => a -> a -> a
* Double
v forall a. Num a => a -> a -> a
* Double
theta
    in IO Double
loop
  | Bool
otherwise  =
    do Double
x <- IO Double -> IO Double -> Double -> Double -> IO Double
generateGamma01 IO Double
gn IO Double
gu (Double
1 forall a. Num a => a -> a -> a
+ Double
kappa) Double
theta
       Double
u <- IO Double
gu
       forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
x forall a. Num a => a -> a -> a
* Double
u forall a. Floating a => a -> a -> a
** (Double
1 forall a. Fractional a => a -> a -> a
/ Double
kappa)

-- | Generate a random number from the Beta distribution.
generateBeta01 :: IO Double
                  -- ^ a normal random number ~ N (0, 1)
                  -> IO Double
                  -- ^ an uniform random number ~ U (0, 1)
                  -> Double
                  -- ^ the shape parameter alpha
                  -> Double
                  -- ^ the shape parameter beta
                  -> IO Double
generateBeta01 :: IO Double -> IO Double -> Double -> Double -> IO Double
generateBeta01 IO Double
gn IO Double
gu Double
alpha Double
beta =
  do Double
g1 <- IO Double -> IO Double -> Double -> Double -> IO Double
generateGamma01 IO Double
gn IO Double
gu Double
alpha Double
1
     Double
g2 <- IO Double -> IO Double -> Double -> Double -> IO Double
generateGamma01 IO Double
gn IO Double
gu Double
beta Double
1
     forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
g1 forall a. Fractional a => a -> a -> a
/ (Double
g1 forall a. Num a => a -> a -> a
+ Double
g2)

-- | Generate a random number from the Weibull distribution.
generateWeibull01 :: IO Double
                     -- ^ an uniform random number ~ U (0, 1)
                     -> Double
                     -- ^ shape
                     -> Double
                     -- ^ scale
                     -> IO Double
generateWeibull01 :: IO Double -> Double -> Double -> IO Double
generateWeibull01 IO Double
g Double
alpha Double
beta =
  do Double
x <- IO Double
g
     forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
beta forall a. Num a => a -> a -> a
* (- forall a. Floating a => a -> a
log Double
x) forall a. Floating a => a -> a -> a
** (Double
1 forall a. Fractional a => a -> a -> a
/ Double
alpha)

-- | Generate a random value from the specified discrete distribution.
generateDiscrete01 :: IO Double
                      -- ^ an uniform random number ~ U (0, 1)
                      -> DiscretePDF a
                      -- ^ a discrete probability density function
                      -> IO a
generateDiscrete01 :: forall a. IO Double -> DiscretePDF a -> IO a
generateDiscrete01 IO Double
g []   = forall a. HasCallStack => [Char] -> a
error [Char]
"Empty PDF: generateDiscrete01"
generateDiscrete01 IO Double
g [(a, Double)]
dpdf =
  do Double
x <- IO Double
g
     let loop :: Double -> [(a, Double)] -> a
loop Double
acc [(a
a, Double
p)] = a
a
         loop Double
acc ((a
a, Double
p) : [(a, Double)]
dpdf) =
           if Double
x forall a. Ord a => a -> a -> Bool
<= Double
acc forall a. Num a => a -> a -> a
+ Double
p
           then a
a
           else Double -> [(a, Double)] -> a
loop (Double
acc forall a. Num a => a -> a -> a
+ Double
p) [(a, Double)]
dpdf
     forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall {a}. Double -> [(a, Double)] -> a
loop Double
0 [(a, Double)]
dpdf

-- | Defines a type of the random number generator.
data GeneratorType = SimpleGenerator
                     -- ^ The simple random number generator.
                   | SimpleGeneratorWithSeed Word32
                     -- ^ The simple random number generator with the specified seed.
                   | CustomGenerator (IO Generator)
                     -- ^ The custom random number generator.
                   | CustomGenerator01 (IO Double)
                     -- ^ The custom random number generator by the specified uniform
                     -- generator of numbers from 0 to 1.

-- | Create a new random number generator by the specified type.
newGenerator :: GeneratorType -> IO Generator
newGenerator :: GeneratorType -> IO Generator
newGenerator GeneratorType
tp =
  case GeneratorType
tp of
    GeneratorType
SimpleGenerator ->
      forall a (m :: * -> *).
(Variate a, PrimMonad m) =>
Gen (PrimState m) -> m a
MWC.uniform forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO GenIO
MWC.createSystemRandom forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO Double -> IO Generator
newRandomGenerator01
    SimpleGeneratorWithSeed Word32
x ->
      forall a (m :: * -> *).
(Variate a, PrimMonad m) =>
Gen (PrimState m) -> m a
MWC.uniform forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) (v :: * -> *).
(PrimMonad m, Vector v Word32) =>
v Word32 -> m (Gen (PrimState m))
MWC.initialize (forall a. a -> Vector a
singleton Word32
x) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO Double -> IO Generator
newRandomGenerator01
    CustomGenerator IO Generator
g ->
      IO Generator
g
    CustomGenerator01 IO Double
g ->
      IO Double -> IO Generator
newRandomGenerator01 IO Double
g

-- | Create a new random generator by the specified standard generator.
newRandomGenerator :: RandomGen g => g -> IO Generator
newRandomGenerator :: forall g. RandomGen g => g -> IO Generator
newRandomGenerator g
g =
  do IORef g
r <- forall a. a -> IO (IORef a)
newIORef g
g
     let g1 :: IO Double
g1 = do g
g <- forall a. IORef a -> IO a
readIORef IORef g
r
                 let (Double
x, g
g') = forall a g. (Random a, RandomGen g) => g -> (a, g)
random g
g
                 forall a. IORef a -> a -> IO ()
writeIORef IORef g
r g
g'
                 forall (m :: * -> *) a. Monad m => a -> m a
return Double
x
     IO Double -> IO Generator
newRandomGenerator01 IO Double
g1

-- | Create a new random generator by the specified uniform generator of numbers from 0 to 1.
newRandomGenerator01 :: IO Double -> IO Generator
newRandomGenerator01 :: IO Double -> IO Generator
newRandomGenerator01 IO Double
g =
  do let g1 :: IO Double
g1 = IO Double
g
     IO Double
g2 <- IO Double -> IO (IO Double)
newNormalGenerator01 IO Double
g1
     let g3 :: Double -> Double -> IO Double
g3 Double
mu Double
nu = do { Double
x <- IO Double
g2; forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double
mu forall a. Num a => a -> a -> a
+ Double
nu forall a. Num a => a -> a -> a
* Double
x }
         g4 :: Double -> Double -> IO Double
g4 Double
mu Double
nu = do { Double
x <- IO Double
g2; forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Floating a => a -> a
exp (Double
mu forall a. Num a => a -> a -> a
+ Double
nu forall a. Num a => a -> a -> a
* Double
x) }
     IORef Int
seqNoRef <- forall a. a -> IO (IORef a)
newIORef Int
0
     let seqNo :: IO Int
seqNo = do { Int
x <- forall a. IORef a -> IO a
readIORef IORef Int
seqNoRef; forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef Int
seqNoRef (forall a. Num a => a -> a -> a
+Int
1); forall (m :: * -> *) a. Monad m => a -> m a
return Int
x }
     forall (m :: * -> *) a. Monad m => a -> m a
return Generator { generateUniform :: Double -> Double -> IO Double
generateUniform = IO Double -> Double -> Double -> IO Double
generateUniform01 IO Double
g1,
                        generateUniformInt :: Int -> Int -> IO Int
generateUniformInt = IO Double -> Int -> Int -> IO Int
generateUniformInt01 IO Double
g1,
                        generateTriangular :: Double -> Double -> Double -> IO Double
generateTriangular = IO Double -> Double -> Double -> Double -> IO Double
generateTriangular01 IO Double
g1,
                        generateNormal :: Double -> Double -> IO Double
generateNormal = Double -> Double -> IO Double
g3,
                        generateLogNormal :: Double -> Double -> IO Double
generateLogNormal = Double -> Double -> IO Double
g4,
                        generateExponential :: Double -> IO Double
generateExponential = IO Double -> Double -> IO Double
generateExponential01 IO Double
g1,
                        generateErlang :: Double -> Int -> IO Double
generateErlang = IO Double -> Double -> Int -> IO Double
generateErlang01 IO Double
g1,
                        generatePoisson :: Double -> IO Int
generatePoisson = IO Double -> Double -> IO Int
generatePoisson01 IO Double
g1,
                        generateBinomial :: Double -> Int -> IO Int
generateBinomial = IO Double -> Double -> Int -> IO Int
generateBinomial01 IO Double
g1,
                        generateGamma :: Double -> Double -> IO Double
generateGamma = IO Double -> IO Double -> Double -> Double -> IO Double
generateGamma01 IO Double
g2 IO Double
g1,
                        generateBeta :: Double -> Double -> IO Double
generateBeta = IO Double -> IO Double -> Double -> Double -> IO Double
generateBeta01 IO Double
g2 IO Double
g1,
                        generateWeibull :: Double -> Double -> IO Double
generateWeibull = IO Double -> Double -> Double -> IO Double
generateWeibull01 IO Double
g1,
                        generateDiscrete :: forall a. DiscretePDF a -> IO a
generateDiscrete = forall a. IO Double -> DiscretePDF a -> IO a
generateDiscrete01 IO Double
g1,
                        generateSequenceNo :: IO Int
generateSequenceNo = IO Int
seqNo }