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

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

module Data.Random.Distribution.Exponential where

import Data.Random.RVar
import Data.Random.Distribution
import Data.Random.Distribution.Uniform

{-|
A definition of the exponential distribution over the type @a@.

@'Exp' mu@ models an exponential distribution with mean @mu@. This can
alternatively be viewed as an exponential distribution with parameter @lambda =
1 / mu@.

See also 'exponential'.
-}
newtype Exponential a = Exp a

floatingExponential :: (Floating a, Distribution StdUniform a) => a -> RVarT m a
floatingExponential :: a -> RVarT m a
floatingExponential a
lambdaRecip = do
    a
x <- RVarT m a
forall a (m :: * -> *). Distribution StdUniform a => RVarT m a
stdUniformT
    a -> RVarT m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> a
forall a. Num a => a -> a
negate (a -> a
forall a. Floating a => a -> a
log a
x) a -> a -> a
forall a. Num a => a -> a -> a
* a
lambdaRecip)

floatingExponentialCDF :: Real a => a -> a -> Double
floatingExponentialCDF :: a -> a -> Double
floatingExponentialCDF a
lambdaRecip a
x = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double
forall a. Num a => a -> a
negate (a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
x) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
lambdaRecip)

{-|
A random variable which samples from the exponential distribution.

@'exponential' mu@ is an exponential random variable with mean @mu@. This can
alternatively be viewed as an exponential random variable with parameter @lambda
= 1 / mu@.
-}
exponential :: Distribution Exponential a => a -> RVar a
exponential :: a -> RVar a
exponential = Exponential a -> RVar a
forall (d :: * -> *) t. Distribution d t => d t -> RVar t
rvar (Exponential a -> RVar a) -> (a -> Exponential a) -> a -> RVar a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Exponential a
forall a. a -> Exponential a
Exp

{-|
A random variable transformer which samples from the exponential distribution.

@'exponentialT' mu@ is an exponential random variable with mean @mu@. This can
alternatively be viewed as an exponential random variable with parameter @lambda
= 1 / mu@.
-}
exponentialT :: Distribution Exponential a => a -> RVarT m a
exponentialT :: a -> RVarT m a
exponentialT = Exponential a -> RVarT m a
forall (d :: * -> *) t (n :: * -> *).
Distribution d t =>
d t -> RVarT n t
rvarT (Exponential a -> RVarT m a)
-> (a -> Exponential a) -> a -> RVarT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Exponential a
forall a. a -> Exponential a
Exp

instance (Floating a, Distribution StdUniform a) => Distribution Exponential a where
    rvarT :: Exponential a -> RVarT n a
rvarT (Exp a
lambdaRecip) = a -> RVarT n a
forall a (m :: * -> *).
(Floating a, Distribution StdUniform a) =>
a -> RVarT m a
floatingExponential a
lambdaRecip
instance (Real a, Distribution Exponential a) => CDF Exponential a where
    cdf :: Exponential a -> a -> Double
cdf  (Exp a
lambdaRecip) = a -> a -> Double
forall a. Real a => a -> a -> Double
floatingExponentialCDF a
lambdaRecip