module Gev.Gumbel
    (
      GumbelDistribution
    -- * Constructors
    , gumbelDist
    , gumbelDistMaybe
    -- * Accessors
    , location
    , scale
    ) where

import qualified Gev
-- import Numeric.SpecFunctions (log1p,expm1) POSSIBLY!!!

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

instance Show GumbelDistribution where
    show :: GumbelDistribution -> String
show (Gumbel Double
loc Double
sc) = ShowS
forall a. Show a => a -> String
show String
"Gumbel 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
" and scale: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
sc

-- error message when initiating Gumbel with scale parameter less than 0.
gumbelErrMsg :: Double -> Double -> String
gumbelErrMsg :: Double -> Double -> String
gumbelErrMsg Double
loc Double
scale = String
"Gev.Gumbel: " 
    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
", but the scale parameter must be positive!"

-- | create Gumbel Dist, where scale parameter must be greater than 0.
gumbelDistMaybe :: Double -> Double -> Maybe GumbelDistribution
gumbelDistMaybe :: Double -> Double -> Maybe GumbelDistribution
gumbelDistMaybe Double
loc Double
sc
    | Double
sc Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0    = GumbelDistribution -> Maybe GumbelDistribution
forall a. a -> Maybe a
Just (GumbelDistribution -> Maybe GumbelDistribution)
-> GumbelDistribution -> Maybe GumbelDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> GumbelDistribution
Gumbel Double
loc Double
sc
    | Bool
otherwise = Maybe GumbelDistribution
forall a. Maybe a
Nothing

-- | create Gumbel Dist, where scale parameter must be greater than 0.
gumbelDist :: Double -> Double -> GumbelDistribution
gumbelDist :: Double -> Double -> GumbelDistribution
gumbelDist Double
loc Double
sc = GumbelDistribution
-> (GumbelDistribution -> GumbelDistribution)
-> Maybe GumbelDistribution
-> GumbelDistribution
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> GumbelDistribution
forall a. HasCallStack => String -> a
error (String -> GumbelDistribution) -> String -> GumbelDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> String
gumbelErrMsg Double
loc Double
sc) GumbelDistribution -> GumbelDistribution
forall a. a -> a
id (Maybe GumbelDistribution -> GumbelDistribution)
-> Maybe GumbelDistribution -> GumbelDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Maybe GumbelDistribution
gumbelDistMaybe Double
loc Double
sc

-- | The CDF of the Gumbel distribution
cdfGumbel :: GumbelDistribution -> Double -> Double
cdfGumbel :: GumbelDistribution -> Double -> Double
cdfGumbel (Gumbel Double
loc Double
sc) Double
x
    | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0     = Double
0
    | Bool
otherwise  = Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ - (Double -> Double
forall a. Floating a => a -> a
exp Double
y)
        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

-- | The PDf of the Gumbel distribution
pdfGumbel :: GumbelDistribution -> Double -> Double
pdfGumbel :: GumbelDistribution -> Double -> Double
pdfGumbel (Gumbel Double
loc Double
sc) Double
x =
    let exp_y :: Double
exp_y = Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ - (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
- Double
loc) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sc
        const :: Double
const = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sc
    in Double
const Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
exp_y Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ - Double
exp_y)

quantileGumbel :: GumbelDistribution -> Double -> Double
quantileGumbel :: GumbelDistribution -> Double -> Double
quantileGumbel (Gumbel Double
loc Double
sc) 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 = Double
loc Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
sc Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double -> Double
forall a. Floating a => a -> a
log (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ - Double -> Double
forall a. Floating a => a -> a
log Double
x)
    | Bool
otherwise      =
        String -> Double
forall a. HasCallStack => String -> a
error (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
"Gev.GumbelDistribution.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

-- | Gev.Distribution instance implementation for the Gumbel Distribution
instance Gev.Distribution GumbelDistribution where
    cdf :: GumbelDistribution -> Double -> Double
cdf      = GumbelDistribution -> Double -> Double
cdfGumbel
    pdf :: GumbelDistribution -> Double -> Double
pdf      = GumbelDistribution -> Double -> Double
pdfGumbel
    quantile :: GumbelDistribution -> Double -> Double
quantile = GumbelDistribution -> Double -> Double
quantileGumbel