{-# 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 :: Integer -> RVar a
t = T a -> RVar a
forall (d :: * -> *) t. Distribution d t => d t -> RVar t
rvar (T a -> RVar a) -> (Integer -> T a) -> Integer -> RVar a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> T a
forall a. Integer -> T a
T

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

newtype T a = T Integer
    deriving (T a -> T a -> Bool
(T a -> T a -> Bool) -> (T a -> T a -> Bool) -> Eq (T a)
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, Eq (T a)
Eq (T a)
-> (T a -> T a -> Ordering)
-> (T a -> T a -> Bool)
-> (T a -> T a -> Bool)
-> (T a -> T a -> Bool)
-> (T a -> T a -> Bool)
-> (T a -> T a -> T a)
-> (T a -> T a -> T a)
-> Ord (T a)
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
$cp1Ord :: forall a. Eq (T a)
Ord, Int -> T a -> ShowS
[T a] -> ShowS
T a -> String
(Int -> T a -> ShowS)
-> (T a -> String) -> ([T a] -> ShowS) -> Show (T a)
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 :: T a -> RVarT n a
rvarT (T Integer
n)
        | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0     = do
            a
x <- RVarT n a
forall a (m :: * -> *). Distribution Normal a => RVarT m a
stdNormalT
            a
y <- Integer -> RVarT n a
forall t (m :: * -> *).
Distribution ChiSquare t =>
Integer -> RVarT m t
chiSquareT Integer
n
            a -> RVarT n a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
x a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sqrt (Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
n a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y))
        | Bool
otherwise = String -> RVarT n a
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 = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n
            v2 :: Double
v2 = Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
v
            tD :: Double
tD = a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
t
            u :: Double
u = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
tDDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
tD Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
v)
            x :: Double
x = (Double
tD Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
u) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
u Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
u)