module Gev.GevDist 
    (
     GevDistribution
     -- * constructors
    , gevDist
    , gevDistMaybe
     -- * accessors
    , location
    , scale
    , shape
    ) where

import qualified Gev

data GevDistribution = GEV {
      GevDistribution -> Double
location :: {-# UNPACK #-} !Double
    , GevDistribution -> Double
scale    :: {-# UNPACK #-} !Double
    , GevDistribution -> Double
shape    :: {-# UNPACK #-} !Double
    } deriving (GevDistribution -> GevDistribution -> Bool
(GevDistribution -> GevDistribution -> Bool)
-> (GevDistribution -> GevDistribution -> Bool)
-> Eq GevDistribution
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GevDistribution -> GevDistribution -> Bool
$c/= :: GevDistribution -> GevDistribution -> Bool
== :: GevDistribution -> GevDistribution -> Bool
$c== :: GevDistribution -> GevDistribution -> Bool
Eq)

instance Show GevDistribution where
    show :: GevDistribution -> String
show (GEV Double
loc Double
sc Double
sh) = ShowS
forall a. Show a => a -> String
show String
"GEV Distribution; loc: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
loc String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
", scale: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
sc String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" and shape: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
sh

-- error message when initiating GEV Distribution with scale parameter less than 0.
gevErrMsg :: Double -> Double -> Double -> String
gevErrMsg :: Double -> Double -> Double -> String
gevErrMsg Double
loc Double
scale Double
sh = String
"Gev.GevDist: " 
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"loc = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
loc
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" scale = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
scale
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" schape = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
sh
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
", but the scale parameter must be positive!"

gevDistMaybe :: Double -> Double -> Double -> Maybe GevDistribution
gevDistMaybe :: Double -> Double -> Double -> Maybe GevDistribution
gevDistMaybe Double
loc Double
sc Double
sh
    | Double
sc Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 = GevDistribution -> Maybe GevDistribution
forall a. a -> Maybe a
Just (GevDistribution -> Maybe GevDistribution)
-> GevDistribution -> Maybe GevDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> GevDistribution
GEV Double
loc Double
sc Double
sh
    | Bool
otherwise = Maybe GevDistribution
forall a. Maybe a
Nothing

gevDist :: Double -> Double -> Double -> GevDistribution
gevDist :: Double -> Double -> Double -> GevDistribution
gevDist Double
loc Double
sc Double
sh = GevDistribution
-> (GevDistribution -> GevDistribution)
-> Maybe GevDistribution
-> GevDistribution
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> GevDistribution
forall a. HasCallStack => String -> a
error (String -> GevDistribution) -> String -> GevDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> String
gevErrMsg Double
loc Double
sc Double
sh) GevDistribution -> GevDistribution
forall a. a -> a
id (Maybe GevDistribution -> GevDistribution)
-> Maybe GevDistribution -> GevDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> Maybe GevDistribution
gevDistMaybe Double
loc Double
sh Double
sc

-- | helper function: checks that the given x value falls in the valid part of the GEV domain.
-- -- actually this i isn't needed, just included as a guard pattern it'll be fine..
gevDomainCheck :: GevDistribution -> Double -> Bool
gevDomainCheck :: GevDistribution -> Double -> Bool
gevDomainCheck (GEV Double
loc Double
sc Double
sh) Double
x =
    if Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
sh Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
loc Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sc) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 then Bool
True else Bool
False

-- | t(x) function depends on if the shape parameter (\zeta) is 0 or not.
-- t(x) = \exp \left(x) = \left( 1 + \zeta \left( \frac{x - \mu}{ \sigma} \right) \right)^{- \frac{1}{\zeta}}$$ if $\zeta \neq 0$,
--  or $t(x) = \exp \left \{ - \frac{x - \mu}{ \sigma }  \right \}$ if $\zeta = 0$
gevArg :: Double -> Double -> Double -> Double -> Double
gevArg :: Double -> Double -> Double -> Double -> Double
gevArg Double
loc Double
sc Double
sh Double
x =
    if Double
sh Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 then Double
one else Double
two
        where
            y :: Double
y   = (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
loc) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sc
            one :: Double
one = Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ - Double
y
            two :: Double
two = (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
sh Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (- Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sh)
   
-- | CDF of the GEV Distribution.
cdfGEV :: GevDistribution -> Double -> Double
cdfGEV :: GevDistribution -> Double -> Double
cdfGEV (GEV Double
loc Double
sc Double
sh) Double
x
   | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0                       = Double
0
   | Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
sh Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
loc Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sc) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0  = Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ - Double
tVal
   | Bool
otherwise =
        String -> Double
forall a. HasCallStack => String -> a
error (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
"Gev.GevDist.cdf: The given x value is not in the support of the Distribution: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
x
   where
       tVal :: Double
tVal = Double -> Double -> Double -> Double -> Double
gevArg Double
loc Double
sc Double
sh Double
x
        

-- | PDF of the GEV Distribution.
pdfGEV :: GevDistribution -> Double -> Double
pdfGEV :: GevDistribution -> Double -> Double
pdfGEV (GEV Double
loc Double
sc Double
sh) Double
x
   | Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
sh Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
loc Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sc) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0  = Double
const Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
middle Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
exp ( - Double
tVal)
   | Bool
otherwise =
        String -> Double
forall a. HasCallStack => String -> a
error (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
"Gev.GevDist.pdf: The given x value is not in the support of the Distribution: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
x
   where
       tVal :: Double
tVal   = Double -> Double -> Double -> Double -> Double
gevArg Double
loc Double
sc Double
sh Double
x
       const :: Double
const  = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sc
       middle :: Double
middle = Double
tVal Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (Double
sh Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1)

-- | Quantile function of the GEV Distribution
-- Quantile function of the Frechet Distribution
quantileGEV :: GevDistribution -> Double -> Double
quantileGEV :: GevDistribution -> Double -> Double
quantileGEV (GEV Double
loc Double
sc Double
sh) Double
x
    | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 Bool -> Bool -> Bool
&& Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1 = if Double
sh Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 then Double
one else Double
two
    | Bool
otherwise      =
        String -> Double
forall a. HasCallStack => String -> a
error (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
"Gev.GEVDist.quantile: The given value must be between 0 and 1, got: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
x
    where 
        logx :: Double
logx  = - Double -> Double
forall a. Floating a => a -> a
log Double
x
        one :: Double
one   = - Double
sc Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
log Double
logx Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
loc
        const :: Double
const = Double
sc Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sh
        two :: Double
two   = Double
const Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
logx Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (- Double
sh)) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
const Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
loc

instance Gev.Distribution GevDistribution where
    cdf :: GevDistribution -> Double -> Double
cdf      = GevDistribution -> Double -> Double
cdfGEV
    pdf :: GevDistribution -> Double -> Double
pdf      = GevDistribution -> Double -> Double
pdfGEV
    quantile :: GevDistribution -> Double -> Double
quantile = GevDistribution -> Double -> Double
quantileGEV