{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE UndecidableInstances  #-}

{-# OPTIONS_GHC -Wall                      #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing   #-}
{-# OPTIONS_GHC -fno-warn-type-defaults    #-}
{-# OPTIONS_GHC -fno-warn-unused-do-bind   #-}
{-# OPTIONS_GHC -fno-warn-missing-methods  #-}
{-# OPTIONS_GHC -fno-warn-orphans          #-}

{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}

module Data.Random.Distribution.T where

import Data.RVar
import Data.Random.Distribution
import Data.Random.Distribution.ChiSquare
import Data.Random.Distribution.Normal

import Numeric.SpecFunctions

t :: Distribution T a => Integer -> RVar a
t :: forall a. Distribution T a => Integer -> RVar a
t = forall (d :: * -> *) t. Distribution d t => d t -> RVar t
rvar forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Integer -> T a
T

tT :: Distribution T a => Integer -> RVarT m a
tT :: forall a (m :: * -> *). Distribution T a => Integer -> RVarT m a
tT = forall (d :: * -> *) t (n :: * -> *).
Distribution d t =>
d t -> RVarT n t
rvarT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Integer -> T a
T

newtype T a = T Integer
    deriving (T a -> T a -> Bool
forall a. T a -> T a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: T a -> T a -> Bool
$c/= :: forall a. T a -> T a -> Bool
== :: T a -> T a -> Bool
$c== :: forall a. T a -> T a -> Bool
Eq, T a -> T a -> Bool
T a -> T a -> Ordering
T a -> T a -> T a
forall a. Eq (T a)
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. T a -> T a -> Bool
forall a. T a -> T a -> Ordering
forall a. T a -> T a -> T a
min :: T a -> T a -> T a
$cmin :: forall a. T a -> T a -> T a
max :: T a -> T a -> T a
$cmax :: forall a. T a -> T a -> T a
>= :: T a -> T a -> Bool
$c>= :: forall a. T a -> T a -> Bool
> :: T a -> T a -> Bool
$c> :: forall a. T a -> T a -> Bool
<= :: T a -> T a -> Bool
$c<= :: forall a. T a -> T a -> Bool
< :: T a -> T a -> Bool
$c< :: forall a. T a -> T a -> Bool
compare :: T a -> T a -> Ordering
$ccompare :: forall a. T a -> T a -> Ordering
Ord, Int -> T a -> ShowS
forall a. Int -> T a -> ShowS
forall a. [T a] -> ShowS
forall a. T a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [T a] -> ShowS
$cshowList :: forall a. [T a] -> ShowS
show :: T a -> String
$cshow :: forall a. T a -> String
showsPrec :: Int -> T a -> ShowS
$cshowsPrec :: forall a. Int -> T a -> ShowS
Show)

instance (Floating a, Distribution Normal a, Distribution ChiSquare a) => Distribution T a where
    rvarT :: forall (n :: * -> *). T a -> RVarT n a
rvarT (T Integer
n)
        | Integer
n forall a. Ord a => a -> a -> Bool
> Integer
0     = do
            a
x <- forall a (m :: * -> *). Distribution Normal a => RVarT m a
stdNormalT
            a
y <- forall t (m :: * -> *).
Distribution ChiSquare t =>
Integer -> RVarT m t
chiSquareT Integer
n
            forall (m :: * -> *) a. Monad m => a -> m a
return (a
x forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sqrt (forall a. Num a => Integer -> a
fromInteger Integer
n forall a. Fractional a => a -> a -> a
/ a
y))
        | Bool
otherwise = forall a. HasCallStack => String -> a
error String
"Student's t-distribution: degrees of freedom must be positive"

instance (Real a, Distribution T a) => CDF T a where
    cdf :: T a -> a -> Double
cdf (T Integer
n) a
t = Double -> Double -> Double -> Double
incompleteBeta Double
v2 Double
v2 Double
x
        where
            v :: Double
v = forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n
            v2 :: Double
v2 = Double
0.5 forall a. Num a => a -> a -> a
* Double
v
            tD :: Double
tD = forall a b. (Real a, Fractional b) => a -> b
realToFrac a
t
            u :: Double
u = forall a. Floating a => a -> a
sqrt (Double
tDforall a. Num a => a -> a -> a
*Double
tD forall a. Num a => a -> a -> a
+ Double
v)
            x :: Double
x = (Double
tD forall a. Num a => a -> a -> a
+ Double
u) forall a. Fractional a => a -> a -> a
/ (Double
u forall a. Num a => a -> a -> a
+ Double
u)