module Data.Random.Distribution.Normal where
import Data.Random.Source
import Data.Random.Distribution
import Data.Random.Distribution.Uniform
import Data.Random.RVar
import Control.Monad
normalPair :: (Floating a, Distribution Uniform a) => RVar (a,a)
normalPair = do
u <- uniform 0 1
t <- uniform 0 (2 * pi)
let r = sqrt (2 * log u)
x = r * cos t
y = r * sin t
return (x,y)
knuthPolarNormalPair :: (Floating a, Ord a, Distribution Uniform a) => RVar (a,a)
knuthPolarNormalPair = do
v1 <- uniform (1) 1
v2 <- uniform (1) 1
let s = v1*v1 + v2*v2
if s >= 1
then knuthPolarNormalPair
else return $ if s == 0
then (0,0)
else let scale = sqrt (2 * log s / s)
in (v1 * scale, v2 * scale)
realFloatStdNormal :: RealFloat a => RVar a
realFloatStdNormal = do
u <- realFloatStdUniform
t <- realFloatStdUniform
let r = sqrt (2 * log u)
x = r * cos (t * 2 * pi)
return x
data Normal a
= StdNormal
| Normal a a
instance (Floating a, Distribution Uniform a) => Distribution Normal a where
rvar StdNormal = liftM fst normalPair
rvar (Normal m s) = do
x <- liftM fst normalPair
return (x * s + m)
stdNormal :: Distribution Normal a => RVar a
stdNormal = rvar StdNormal
normal :: Distribution Normal a => a -> a -> RVar a
normal m s = rvar (Normal m s)