{-# LANGUAGE
MultiParamTypeClasses,
FlexibleInstances, FlexibleContexts,
UndecidableInstances,
TemplateHaskell
#-}
{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}
module Data.Random.Distribution.Beta where
import Data.Random.Internal.TH
import Data.Random.RVar
import Data.Random.Distribution
import Data.Random.Distribution.Gamma
import Data.Random.Distribution.Uniform
import Numeric.SpecFunctions
{-# SPECIALIZE fractionalBeta :: Float -> Float -> RVarT m Float #-}
{-# SPECIALIZE fractionalBeta :: Double -> Double -> RVarT m Double #-}
fractionalBeta :: (Fractional a, Eq a, Distribution Gamma a, Distribution StdUniform a) => a -> a -> RVarT m a
fractionalBeta 1 1 = stdUniformT
fractionalBeta a b = do
x <- gammaT a 1
y <- gammaT b 1
return (x / (x + y))
{-# SPECIALIZE beta :: Float -> Float -> RVar Float #-}
{-# SPECIALIZE beta :: Double -> Double -> RVar Double #-}
beta :: Distribution Beta a => a -> a -> RVar a
beta a b = rvar (Beta a b)
{-# SPECIALIZE betaT :: Float -> Float -> RVarT m Float #-}
{-# SPECIALIZE betaT :: Double -> Double -> RVarT m Double #-}
betaT :: Distribution Beta a => a -> a -> RVarT m a
betaT a b = rvarT (Beta a b)
data Beta a = Beta a a
logBetaPdf :: Double -> Double -> Double -> Double
logBetaPdf a b x
| a <= 0 || b <= 0 = nan
| x <= 0 = log 0
| x >= 1 = log 0
| otherwise = (a-1)*log x + (b-1)*log (1-x) - logBeta a b
where
nan = 0.0 / 0.0
instance PDF Beta Double
where
pdf (Beta a b) = exp . logBetaPdf a b
instance PDF Beta Float
where
pdf (Beta a b) = realToFrac . exp . logBetaPdf (realToFrac a) (realToFrac b) . realToFrac
$( replicateInstances ''Float realFloatTypes [d|
instance Distribution Beta Float
where rvarT (Beta a b) = fractionalBeta a b
|])