module Statistics.Distribution.StudentT (
StudentT
, studentT
, studentTndf
) where
import qualified Statistics.Distribution as D
import Data.Typeable (Typeable)
import Numeric.SpecFunctions (logBeta, incompleteBeta, invIncompleteBeta)
newtype StudentT = StudentT { studentTndf :: Double }
deriving (Eq,Show,Read,Typeable)
studentT :: Double -> StudentT
studentT ndf
| ndf > 0 = StudentT ndf
| otherwise =
error "Statistics.Distribution.StudentT.studentT: non-positive number of degrees of freedom"
instance D.Distribution StudentT where
cumulative = cumulative
instance D.ContDistr StudentT where
density = density
quantile = quantile
cumulative :: StudentT -> Double -> Double
cumulative (StudentT ndf) x
| x > 0 = 1 0.5 * ibeta
| otherwise = 0.5 * ibeta
where
ibeta = incompleteBeta (0.5 * ndf) 0.5 (ndf / (ndf + x*x))
density :: StudentT -> Double -> Double
density (StudentT ndf) x =
exp( log (ndf / (ndf + x*x)) * (0.5 * (1 + ndf)) logBeta 0.5 (0.5 * ndf) ) / sqrt ndf
quantile :: StudentT -> Double -> Double
quantile (StudentT ndf) p
| p >= 0 && p <= 1 =
let x = invIncompleteBeta (0.5 * ndf) 0.5 (2 * min p (1 p))
in case sqrt $ ndf * (1 x) / x of
r | p < 0.5 -> r
| otherwise -> r
| otherwise =
error $ "Statistics.Distribution.Uniform.quantile: p must be in [0,1] range. Got: "++show p
instance D.MaybeMean StudentT where
maybeMean (StudentT ndf) | ndf > 1 = Just 0
| otherwise = Nothing
instance D.MaybeVariance StudentT where
maybeStdDev (StudentT ndf) | ndf > 2 = Just $ ndf / (ndf 2)
| otherwise = Nothing
instance D.ContGen StudentT where
genContVar = D.genContinous